- Media (voice/video/image/file): private bucket, presigned PUT upload, reference-only publish, membership-gated presigned GET for viewing - Avatars: public bucket, presigned PUT + direct public URL, profile.update event - messages.media_key + media_meta (migration 1720000000005_media) - Explicit MinIO region on presigning client (avoids getBucketRegion network call) - Event type values sourced from EventType constants (no raw string literals) - Web: attach button, MediaView renderer, avatar upload in topbar Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFRyKxkKEjfAgpXygzoNiD
67 lines
2 KiB
TypeScript
67 lines
2 KiB
TypeScript
import type { FromSchema } from 'json-schema-to-ts';
|
|
import { mediaRefSchema } from './media';
|
|
|
|
const USERNAME_PATTERN = '^[a-zA-Z0-9_]{3,32}$';
|
|
|
|
export const createDirectBodySchema = {
|
|
type: 'object',
|
|
additionalProperties: false,
|
|
required: ['username'],
|
|
properties: {
|
|
username: { type: 'string', pattern: USERNAME_PATTERN },
|
|
},
|
|
} as const;
|
|
|
|
export const createGroupBodySchema = {
|
|
type: 'object',
|
|
additionalProperties: false,
|
|
required: ['title'],
|
|
properties: {
|
|
title: { type: 'string', minLength: 1, maxLength: 100 },
|
|
members: {
|
|
type: 'array',
|
|
maxItems: 200,
|
|
items: { type: 'string', pattern: USERNAME_PATTERN },
|
|
},
|
|
},
|
|
} as const;
|
|
|
|
export const addMemberBodySchema = {
|
|
type: 'object',
|
|
additionalProperties: false,
|
|
required: ['username'],
|
|
properties: {
|
|
username: { type: 'string', pattern: USERNAME_PATTERN },
|
|
},
|
|
} as const;
|
|
|
|
export const sendMessageBodySchema = {
|
|
type: 'object',
|
|
additionalProperties: false,
|
|
required: ['clientMsgId'],
|
|
properties: {
|
|
// Caption; may be empty for a media-only message.
|
|
content: { type: 'string', maxLength: 16000 },
|
|
clientMsgId: { type: 'string', minLength: 1, maxLength: 64 },
|
|
contentType: { type: 'string', enum: ['text', 'text/ciphertext'] },
|
|
encryption: { type: ['string', 'null'] },
|
|
// Object key returned by the media upload URL + its metadata.
|
|
mediaKey: { type: 'string', minLength: 1, maxLength: 255 },
|
|
media: mediaRefSchema,
|
|
},
|
|
} as const;
|
|
|
|
export const addContactBodySchema = {
|
|
type: 'object',
|
|
additionalProperties: false,
|
|
required: ['username'],
|
|
properties: {
|
|
username: { type: 'string', pattern: USERNAME_PATTERN },
|
|
},
|
|
} as const;
|
|
|
|
export type CreateDirectBody = FromSchema<typeof createDirectBodySchema>;
|
|
export type CreateGroupBody = FromSchema<typeof createGroupBodySchema>;
|
|
export type AddMemberBody = FromSchema<typeof addMemberBodySchema>;
|
|
export type SendMessageBody = FromSchema<typeof sendMessageBodySchema>;
|
|
export type AddContactBody = FromSchema<typeof addContactBodySchema>;
|