/
githubmirror
/
zulip
Обзор
Документация
Войти
/
githubmirror
/
zulip
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
web/src/state_data.ts
748 строк
26 KB
apoorvapendse
search: Add support for date operator.
14 июл 2026, 13:46
14 июл 2026, 13:46
4148079
Код
Авторство
О чём код?
import * as z from "zod/mini"; import {server_add_bot_schema} from "./bot_types.ts"; import {realm_default_settings_schema} from "./realm_user_settings_defaults.ts"; import {api_stream_subscription_schema, never_subscribed_stream_schema} from "./stream_types.ts"; import {group_setting_value_schema} from "./types.ts"; import {user_settings_schema} from "./user_settings.ts"; import {user_status_schema} from "./user_status_types.ts"; const NOT_TYPED_YET = z.optional(z.unknown()); const group_permission_setting_schema = z.object({ require_system_group: z.boolean(), allow_internet_group: z.boolean(), allow_nobody_group: z.boolean(), allow_everyone_group: z.boolean(), default_group_name: z.string(), default_for_system_groups: z.nullable(z.string()), allowed_system_groups: z.array(z.string()), }); export type GroupPermissionSetting = z.output<typeof group_permission_setting_schema>; // We cannot parse the operand since it is incomplete, // only used for generating suggestions. export type NarrowTermSuggestion = { operator: NarrowTerm["operator"]; operand: string; negated?: boolean | undefined; }; export type NarrowCanonicalTermSuggestion = { operator: NarrowCanonicalTerm["operator"]; operand: string; // The operand as the user actually typed it, before any // canonicalization from a name to a user id (e.g. `dm:John` // becomes `dm:50` when "John" is a unique full name). People // suggestions match against this so that completing a unique name // does not hide other name matches like "John Doe". raw_operand: string; negated?: boolean | undefined; }; export const narrow_canonical_operator_schema = z.enum([ "", // Used for search suggestions. "channel", "channels", "date", "dm", "dm-including", "has", "id", "in", "is", "mentions", "near", "search", "sender", "topic", "with", ]); export type NarrowCanonicalOperator = z.output<typeof narrow_canonical_operator_schema>; const narrow_legacy_operator_schema = z.enum([ "pm-with", "group-pm-with", "from", "stream", "streams", "subject", ]); export const narrow_operator_schema = z.union([ narrow_canonical_operator_schema, narrow_legacy_operator_schema, ]); export type NarrowOperator = z.output<typeof narrow_operator_schema>; export const narrow_canonical_term_schema = z.discriminatedUnion("operator", [ z.object({ operator: z.literal(""), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("channel"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("channels"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("has"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("id"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("in"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("is"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("near"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("search"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("topic"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("with"), operand: z.string(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("mentions"), operand: z.number(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("sender"), operand: z.number(), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("dm-including"), operand: z.array(z.number()), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("dm"), operand: z.array(z.number()), negated: z.optional(z.boolean()), }), z.object({ operator: z.literal("date"), operand: z.string(), negated: z.optional(z.boolean()), }), ]); export type NarrowCanonicalTerm = z.output<typeof narrow_canonical_term_schema>; export const narrow_term_schema = z.union([ narrow_canonical_term_schema, z.object({ negated: z.optional(z.boolean()), operator: narrow_legacy_operator_schema, operand: z.string(), }), ]); export type NarrowTerm = z.output<typeof narrow_term_schema>; export const custom_profile_field_schema = z.object({ display_in_profile_summary: z.optional(z.boolean()), editable_by_user: z.boolean(), field_data: z.string(), hint: z.string(), id: z.number(), name: z.string(), order: z.number(), required: z.boolean(), type: z.number(), use_for_user_matching: z.optional(z.boolean()), }); export type CustomProfileField = z.output<typeof custom_profile_field_schema>; export const scheduled_message_schema = z.intersection( z.object({ scheduled_message_id: z.number(), content: z.string(), rendered_content: z.string(), scheduled_delivery_timestamp: z.number(), failed: z.boolean(), }), z.discriminatedUnion("type", [ z.object({ type: z.literal("private"), to: z.array(z.number()), }), z.object({ type: z.literal("stream"), to: z.number(), topic: z.string(), }), ]), ); export const reminder_schema = z.object({ reminder_id: z.number(), type: z.literal("private"), to: z.array(z.number()), content: z.string(), rendered_content: z.string(), scheduled_delivery_timestamp: z.number(), failed: z.boolean(), reminder_target_message_id: z.number(), }); export const profile_datum_schema = z.object({ value: z.string(), rendered_value: z.nullish(z.string()), }); export const user_schema = z.intersection( z.object({ user_id: z.number(), delivery_email: z.nullable(z.string()), email: z.string(), full_name: z.string(), // used for caching result of remove_diacritics. name_with_diacritics_removed: z.optional(z.string()), date_joined: z.string(), is_active: z.optional(z.boolean()), is_owner: z.boolean(), is_admin: z.boolean(), is_guest: z.boolean(), is_deleted: z.optional(z.literal(true)), is_moderator: z.optional(z.boolean()), role: z.number(), timezone: z.optional(z.string()), avatar_url: z.nullish(z.string()), avatar_version: z.number(), profile_data: z.optional(z.record(z.coerce.number<string>(), profile_datum_schema)), is_imported_stub: z.boolean(), // used for fake user objects. is_missing_server_data: z.optional(z.boolean()), // used for inaccessible user objects. is_inaccessible_user: z.optional(z.boolean()), is_system_bot: z.optional(z.literal(true)), }), z.discriminatedUnion("is_bot", [ z.object({ is_bot: z.literal(false), bot_type: z.optional(z.null()), }), z.object({ is_bot: z.literal(true), bot_type: z.number(), bot_owner_id: z.nullable(z.number()), }), ]), ); export const server_emoji_schema = z.object({ id: z.string(), author_id: z.number(), deactivated: z.boolean(), name: z.string(), source_url: z.string(), still_url: z.nullable(z.string()), // Added later in `settings_emoji.ts` when setting up the emoji settings. author: z.nullish(user_schema), }); export const realm_emoji_map_schema = z.record(z.string(), server_emoji_schema); export type GroupSettingValue = z.infer<typeof group_setting_value_schema>; export const raw_user_group_schema = z.object({ description: z.string(), id: z.number(), creator_id: z.nullable(z.number()), date_created: z.nullable(z.number()), name: z.string(), members: z.array(z.number()), is_system_group: z.boolean(), direct_subgroup_ids: z.array(z.number()), can_add_members_group: group_setting_value_schema, can_join_group: group_setting_value_schema, can_leave_group: group_setting_value_schema, can_manage_group: group_setting_value_schema, can_mention_group: group_setting_value_schema, can_remove_members_group: group_setting_value_schema, deactivated: z.boolean(), }); export const channel_folder_schema = z.object({ id: z.number(), name: z.string(), description: z.string(), rendered_description: z.string(), creator_id: z.nullable(z.number()), date_created: z.number(), is_archived: z.boolean(), order: z.number(), }); export const navigation_view_schema = z.object({ fragment: z.string(), name: z.nullable(z.string()), is_pinned: z.boolean(), }); export type NavigationView = z.infer<typeof navigation_view_schema>; export const user_topic_schema = z.object({ stream_id: z.number(), topic_name: z.string(), last_updated: z.number(), visibility_policy: z.number(), }); export const muted_user_schema = z.object({ id: z.number(), timestamp: z.number(), }); const unread_stream_info_schema = z.object({ stream_id: z.number(), topic: z.string(), unread_message_ids: z.array(z.number()), }); export const unread_direct_message_info_schema = z.object({ other_user_id: z.number(), unread_message_ids: z.array(z.number()), }); export const unread_direct_message_group_info_schema = z.object({ user_ids_string: z.string(), unread_message_ids: z.array(z.number()), }); export const presence_schema = z.object({ active_timestamp: z.optional(z.number()), idle_timestamp: z.optional(z.number()), }); export const realm_billing_schema = z.object({ has_pending_sponsorship_request: z.boolean(), }); export const saved_snippet_schema = z.object({ id: z.number(), title: z.string(), content: z.string(), date_created: z.number(), }); const one_time_notice_schema = z.object({ name: z.string(), type: z.literal("one_time_notice"), }); const one_time_action_schema = z.object({ name: z.string(), type: z.literal("one_time_action"), }); export const thumbnail_format_schema = z.object({ name: z.string(), max_width: z.number(), max_height: z.number(), format: z.string(), animated: z.boolean(), }); export const onboarding_step_schema = z.union([one_time_notice_schema, one_time_action_schema]); // Sync this with zerver.lib.events.do_events_register. const current_user_schema = z.object({ avatar_source: z.string(), avatar_url: z.nullish(z.string()), avatar_url_medium: z.nullish(z.string()), can_create_private_streams: z.boolean(), can_create_public_streams: z.boolean(), can_create_streams: z.boolean(), can_create_web_public_streams: z.boolean(), can_invite_others_to_realm: z.boolean(), delivery_email: z.string(), email: z.string(), full_name: z.string(), has_zoom_token: z.boolean(), has_webex_token: z.boolean(), is_admin: z.boolean(), is_guest: z.boolean(), is_moderator: z.boolean(), is_owner: z.boolean(), user_id: z.number(), }); const custom_profile_field_types_schema = z.object({ SHORT_TEXT: z.object({id: z.number(), name: z.string()}), PARAGRAPH: z.object({id: z.number(), name: z.string()}), DATE: z.object({id: z.number(), name: z.string()}), DROPDOWN: z.object({id: z.number(), name: z.string()}), URL: z.object({id: z.number(), name: z.string()}), EXTERNAL_ACCOUNT: z.object({id: z.number(), name: z.string()}), USER: z.object({id: z.number(), name: z.string()}), PRONOUNS: z.object({id: z.number(), name: z.string()}), }); export type CustomProfileFieldTypes = z.infer<typeof custom_profile_field_types_schema>; export const realm_domain_schema = z.object({ domain: z.string(), allow_subdomains: z.boolean(), }); export const realm_playground_schema = z.object({ id: z.number(), name: z.string(), pygments_language: z.string(), url_template: z.string(), }); export const realm_linkifier_schema = z.object({ pattern: z.string(), url_template: z.string(), id: z.number(), example_input: z.optional(z.nullable(z.string())), reverse_template: z.optional(z.nullable(z.string())), alternative_url_templates: z.optional(z.array(z.string())), }); export const realm_report_message_types = z.object({ key: z.string(), name: z.string(), }); // Sync this with zerver.lib.events.do_events_register. export const realm_schema = z.object({ custom_profile_fields: z.array(custom_profile_field_schema), custom_profile_field_types: custom_profile_field_types_schema, demo_organization_scheduled_deletion_date: z.optional(z.number()), giphy_api_key: z.string(), gif_rating_policy_options: z.intersection( z.record(z.string(), z.object({id: z.number(), name: z.string()})), z.object({disabled: z.object({id: z.number(), name: z.string()})}), ), max_avatar_file_size_mib: z.number(), max_channel_folder_description_length: z.number(), max_channel_folder_name_length: z.number(), max_file_upload_size_mib: z.number(), max_icon_file_size_mib: z.number(), max_logo_file_size_mib: z.number(), max_message_length: z.number(), max_reminder_note_length: z.number(), max_stream_description_length: z.number(), max_stream_name_length: z.number(), max_topic_length: z.number(), max_bulk_new_subscription_messages: z.number(), password_min_guesses: z.number(), password_min_length: z.number(), password_max_length: z.number(), realm_allow_message_editing: z.boolean(), realm_authentication_methods: z.record( z.string(), z.object({ enabled: z.boolean(), available: z.boolean(), unavailable_reason: z.optional(z.string()), }), ), realm_available_video_chat_providers: z.object({ disabled: z.object({name: z.string(), id: z.number()}), jitsi_meet: z.object({name: z.string(), id: z.number()}), zoom: z.optional(z.object({name: z.string(), id: z.number()})), zoom_server_to_server: z.optional(z.object({name: z.string(), id: z.number()})), big_blue_button: z.optional(z.object({name: z.string(), id: z.number()})), constructor_groups: z.optional(z.object({name: z.string(), id: z.number()})), nextcloud_talk: z.optional(z.object({name: z.string(), id: z.number()})), webex: z.optional(z.object({name: z.string(), id: z.number()})), }), realm_avatar_changes_disabled: z.boolean(), realm_bot_domain: z.string(), realm_can_access_all_users_group: z.number(), realm_can_add_custom_emoji_group: group_setting_value_schema, realm_can_add_subscribers_group: group_setting_value_schema, realm_can_create_bots_group: group_setting_value_schema, realm_can_create_groups: group_setting_value_schema, realm_can_create_public_channel_group: group_setting_value_schema, realm_can_create_private_channel_group: group_setting_value_schema, realm_can_create_web_public_channel_group: z.number(), realm_can_create_write_only_bots_group: group_setting_value_schema, realm_can_delete_any_message_group: group_setting_value_schema, realm_can_delete_own_message_group: group_setting_value_schema, realm_can_invite_users_group: group_setting_value_schema, realm_can_manage_all_groups: group_setting_value_schema, realm_can_manage_billing_group: group_setting_value_schema, realm_can_mention_many_users_group: group_setting_value_schema, realm_can_move_messages_between_channels_group: group_setting_value_schema, realm_can_move_messages_between_topics_group: group_setting_value_schema, realm_can_resolve_topics_group: group_setting_value_schema, realm_can_set_delete_message_policy_group: group_setting_value_schema, realm_can_set_topics_policy_group: group_setting_value_schema, realm_can_summarize_topics_group: group_setting_value_schema, realm_create_multiuse_invite_group: group_setting_value_schema, realm_date_created: z.number(), realm_default_avatar_source: z.enum(["G", "J"]), realm_default_code_block_language: z.string(), realm_default_external_accounts: z.record( z.string(), z.object({ text: z.string(), url_pattern: z.string(), name: z.string(), hint: z.string(), }), ), realm_default_language: z.string(), realm_description: z.string(), realm_digest_emails_enabled: z.boolean(), realm_digest_weekday: z.number(), realm_direct_message_initiator_group: group_setting_value_schema, realm_direct_message_permission_group: group_setting_value_schema, realm_disallow_disposable_email_addresses: z.boolean(), realm_domains: z.array(realm_domain_schema), realm_email_auth_enabled: z.boolean(), realm_email_changes_disabled: z.boolean(), realm_emails_restricted_to_domains: z.boolean(), realm_embedded_bots: z.array( z.object({ name: z.string(), config: z.record(z.string(), z.string()), }), ), realm_empty_topic_display_name: z.string(), realm_enable_guest_user_dm_warning: z.boolean(), realm_enable_guest_user_indicator: z.boolean(), realm_enable_read_receipts: z.boolean(), realm_enable_spectator_access: z.boolean(), realm_gif_rating_policy: z.number(), realm_icon_source: z.string(), realm_icon_url: z.string(), realm_incoming_webhook_bots: z.array( z.object({ display_name: z.string(), name: z.string(), all_event_types: z.nullable(z.array(z.string())), config_options: z.optional( z.array( z.object({ key: z.string(), label: z.string(), validator: z.string(), }), ), ), url_options: z.optional( z.array( z.object({ key: z.string(), label: z.string(), input_type: z.string(), }), ), ), }), ), realm_media_preview_size: z.number(), realm_inline_image_preview: z.boolean(), realm_inline_url_embed_preview: z.boolean(), realm_invite_required: z.boolean(), realm_jitsi_server_url: z.nullable(z.string()), realm_linkifiers: z.array(realm_linkifier_schema), realm_logo_source: z.string(), realm_logo_url: z.string(), realm_message_content_allowed_in_email_notifications: z.boolean(), realm_message_content_edit_limit_seconds: z.nullable(z.number()), realm_message_content_delete_limit_seconds: z.nullable(z.number()), realm_message_edit_history_visibility_policy: z.enum(["all", "moves", "none"]), realm_message_retention_days: z.number(), realm_moderation_request_channel_id: z.number(), realm_move_messages_between_streams_limit_seconds: z.nullable(z.number()), realm_move_messages_within_stream_limit_seconds: z.nullable(z.number()), realm_name_changes_disabled: z.boolean(), realm_name: z.string(), realm_new_stream_announcements_stream_id: z.number(), realm_night_logo_source: z.string(), realm_night_logo_url: z.string(), realm_org_type: z.number(), realm_owner_full_content_access: z.boolean(), realm_password_auth_enabled: z.boolean(), realm_plan_type: z.number(), realm_playgrounds: z.array(realm_playground_schema), realm_presence_disabled: z.boolean(), realm_push_notifications_enabled: z.boolean(), realm_push_notifications_enabled_end_timestamp: z.nullable(z.number()), realm_require_e2ee_push_notifications: z.boolean(), realm_require_unique_names: z.boolean(), realm_send_channel_events_messages: z.boolean(), realm_send_welcome_emails: z.boolean(), realm_signup_announcements_stream_id: z.number(), realm_topics_policy: z.enum(["allow_empty_topic", "disable_empty_topic"]), realm_upload_quota_mib: z.nullable(z.number()), realm_url: z.string(), realm_video_chat_provider: z.number(), realm_waiting_period_threshold: z.number(), realm_want_advertise_in_communities_directory: z.boolean(), realm_welcome_message_custom_text: z.string(), realm_workplace_users_group: group_setting_value_schema, realm_zulip_update_announcements_stream_id: z.number(), server_avatar_changes_disabled: z.boolean(), server_can_summarize_topics: z.boolean(), server_emoji_data_url: z.string(), server_inline_image_preview: z.boolean(), server_inline_url_embed_preview: z.boolean(), server_max_deactivated_realm_deletion_days: z.nullable(z.number()), server_min_deactivated_realm_deletion_days: z.nullable(z.number()), server_jitsi_server_url: z.nullable(z.string()), server_name_changes_disabled: z.boolean(), server_needs_upgrade: z.boolean(), server_presence_offline_threshold_seconds: z.number(), server_presence_ping_interval_seconds: z.number(), server_report_message_types: z.array(realm_report_message_types), server_supported_permission_settings: z.object({ realm: z.record(z.string(), group_permission_setting_schema), stream: z.record(z.string(), group_permission_setting_schema), group: z.record(z.string(), group_permission_setting_schema), }), server_thumbnail_formats: z.array(thumbnail_format_schema), server_typing_started_expiry_period_milliseconds: z.number(), server_typing_started_wait_period_milliseconds: z.number(), server_typing_stopped_wait_period_milliseconds: z.number(), server_web_public_streams_enabled: z.boolean(), settings_send_digest_emails: z.boolean(), stop_words: z.array(z.string()), tenor_api_key: z.string(), klipy_api_key: z.string(), upgrade_text_for_wide_organization_logo: z.string(), zulip_feature_level: z.number(), zulip_merge_base: z.string(), zulip_plan_is_not_limited: z.boolean(), zulip_version: z.string(), }); export const split_state_data_schema = z.object({ alert_words: z.object({alert_words: z.array(z.string())}), emoji: z.object({realm_emoji: realm_emoji_map_schema}), realm_billing: z.object({realm_billing: realm_billing_schema}), bot: z.object({realm_bots: z.array(server_add_bot_schema)}), people: z.object({ realm_users: z.array(user_schema), realm_non_active_users: z.array(user_schema), cross_realm_bots: z.array(user_schema), }), pm_conversations: z.object({ recent_private_conversations: z.array( z.object({ max_message_id: z.number(), user_ids: z.array(z.number()), }), ), }), presence: z.object({ presences: z.record(z.coerce.number<string>(), presence_schema), server_timestamp: z.number(), presence_last_update_id: z.optional(z.number()), }), saved_snippets: z.object({saved_snippets: z.array(saved_snippet_schema)}), starred_messages: z.object({starred_messages: z.array(z.number())}), stream_data: z.object({ subscriptions: z.array(api_stream_subscription_schema), unsubscribed: z.array(api_stream_subscription_schema), never_subscribed: z.array(never_subscribed_stream_schema), realm_default_streams: z.array(z.number()), }), user_groups: z.object({realm_user_groups: z.array(raw_user_group_schema)}), channel_folders: z.object({channel_folders: z.array(channel_folder_schema)}), unread: z.object({ unread_msgs: z.object({ pms: z.array(unread_direct_message_info_schema), streams: z.array(unread_stream_info_schema), huddles: z.array(unread_direct_message_group_info_schema), mentions: z.array(z.number()), count: z.number(), old_unreads_missing: z.boolean(), }), }), muted_users: z.object({muted_users: z.array(muted_user_schema)}), user_topics: z.object({user_topics: z.array(user_topic_schema)}), user_status: z.object({user_status: z.record(z.string(), user_status_schema)}), user_settings: z.object({user_settings: user_settings_schema}), realm_settings_defaults: z.object({ realm_user_settings_defaults: realm_default_settings_schema, }), scheduled_messages: z.object({scheduled_messages: z.array(scheduled_message_schema)}), reminders: z.object({reminders: z.array(reminder_schema)}), server_events_state: z.object({ queue_id: z.nullable(z.string()), }), server_events: z.object({ server_generation: NOT_TYPED_YET, event_queue_longpoll_timeout_seconds: NOT_TYPED_YET, last_event_id: NOT_TYPED_YET, }), local_message: z.object({max_message_id: z.number()}), onboarding_steps: z.object({ onboarding_steps: z.array(onboarding_step_schema), navigation_tour_video_url: z.nullable(z.string()), }), current_user: current_user_schema, realm: realm_schema, navigation_views: z.object({navigation_views: z.array(navigation_view_schema)}), }); type SplitStateDataInput = z.input<typeof split_state_data_schema>; export const state_data_schema = z.pipe( z.transform((state_data: SplitStateDataInput[keyof SplitStateDataInput]) => Object.fromEntries( Object.keys(split_state_data_schema.shape).map((part) => [part, state_data]), ), ), split_state_data_schema, ); export type StateData = z.infer<typeof state_data_schema>; export type CurrentUser = StateData["current_user"]; export type Realm = StateData["realm"]; export type RealmBilling = StateData["realm_billing"]["realm_billing"]; export let current_user: CurrentUser; export let realm: Realm; export let realm_billing: RealmBilling; export function set_current_user(initial_current_user: CurrentUser): void { current_user = initial_current_user; } export function set_realm(initial_realm: Realm): void { realm = initial_realm; } export function set_realm_billing(params: StateData["realm_billing"]): void { realm_billing = params.realm_billing; }