feat(msg): 完整实现 msg 消息服务

包含 channels/preferences/templates/grpc/kafka/outbox/push/redis 等完整实现
This commit is contained in:
SpecialX
2026-07-10 19:09:52 +08:00
parent 21530dc7f6
commit 7b7abbb309
51 changed files with 5204 additions and 371 deletions

View File

@@ -1,14 +1,100 @@
import { z } from "zod";
/**
* msg 服务 DTO + Zod 校验 schema。
*
* 对齐 proto msg.proto 字段:
* - SendNotificationRequest / BatchSendNotificationRequest
* - MarkAsRead / BatchMarkAsRead / MarkAllAsRead
* - SearchNotifications / RecallNotification
*/
// ============================================================
// Send Notification
// ============================================================
export const sendNotificationSchema = z.object({
userId: z.string().min(1),
type: z.string().min(1).max(50),
title: z.string().min(1).max(200),
type: z.string().min(1).max(32),
title: z.string().min(1).max(255),
content: z.string().min(1),
channel: z.string().max(20).optional(),
metadata: z.record(z.unknown()).optional(),
channel: z.string().max(32).optional(),
metadata: z.record(z.string()).optional(),
relatedEntityType: z.string().max(64).optional(),
relatedEntityId: z.string().max(32).optional(),
groupId: z.string().max(32).optional(),
senderId: z.string().max(32).optional(),
templateId: z.string().max(32).optional(),
eventId: z.string().max(64).optional(),
});
export const sendNotificationBatchSchema = z.array(sendNotificationSchema);
export type SendNotificationDto = z.infer<typeof sendNotificationSchema>;
export const sendNotificationBatchSchema = z.object({
items: z.array(sendNotificationSchema).min(1).max(1000),
groupId: z.string().max(32).optional(),
});
export type SendNotificationBatchDto = z.infer<
typeof sendNotificationBatchSchema
>;
// ============================================================
// List / Search
// ============================================================
export const listNotificationsSchema = z.object({
userId: z.string().min(1),
onlyUnread: z.boolean().optional(),
type: z.string().max(32).optional(),
page: z.number().int().min(1).default(1),
pageSize: z.number().int().min(1).max(100).default(20),
});
export type ListNotificationsDto = z.infer<typeof listNotificationsSchema>;
export const searchNotificationsSchema = z.object({
userId: z.string().min(1),
query: z.string().min(1),
type: z.string().max(32).optional(),
page: z.number().int().min(1).default(1),
pageSize: z.number().int().min(1).max(100).default(20),
});
export type SearchNotificationsDto = z.infer<typeof searchNotificationsSchema>;
// ============================================================
// Mark As Read
// ============================================================
export const markAsReadSchema = z.object({
id: z.string().min(1),
userId: z.string().min(1),
});
export type MarkAsReadDto = z.infer<typeof markAsReadSchema>;
export const batchMarkAsReadSchema = z.object({
ids: z.array(z.string().min(1)).min(1).max(1000),
userId: z.string().min(1),
});
export type BatchMarkAsReadDto = z.infer<typeof batchMarkAsReadSchema>;
export const markAllAsReadSchema = z.object({
userId: z.string().min(1),
before: z.number().int().optional(),
});
export type MarkAllAsReadDto = z.infer<typeof markAllAsReadSchema>;
// ============================================================
// Recall
// ============================================================
export const recallNotificationSchema = z.object({
groupId: z.string().min(1),
reason: z.string().max(500).optional(),
});
export type RecallNotificationDto = z.infer<typeof recallNotificationSchema>;