This commit is contained in:
2026-02-23 20:44:34 +03:00
parent 2d0bb1c749
commit d675d3ab9f
6 changed files with 1045 additions and 79 deletions

View File

@@ -2,34 +2,48 @@ import path from 'path'
import protoLoader from '@grpc/proto-loader'
import grpc from '@grpc/grpc-js'
interface Version {
id: number
version: string
// req dto
interface CreateUserDto {
email: string
name?: string
}
interface VersionDto {}
interface GetUserByEmail {
email: string
}
export interface User {
interface UpdateUserDto {
id: number
email: string
token?: string
description?: string
is_admin?: boolean
}
interface GetUserByTokenDto {
token: string
}
interface GetUserByEmailDto {
email: string
}
interface ListUserDto {
page: number
iser_ids: number[]
}
interface CreateChatDto {
name?: string
users: { user_id: number; is_admin?: boolean }[]
}
interface UpdateChat {
id: number
users: { user_id: number; is_admin?: boolean }[]
}
interface GetChatDto {
id: string
}
interface ListChatDto {
page: number
user_ids?: number[]
chat_ids?: string[]
}
interface ListMessageDto {
page: number
chat_id: string
user_id: number
}
interface CreateMessageDto {
@@ -40,45 +54,103 @@ interface CreateMessageDto {
video?: string
file?: string
}
interface UpdateMessageDto {
id: number
chat_id: string
text?: string
image?: string
video?: string
file?: string
}
interface GetMessageDto {
id: number
}
interface ListMessageDto {
page: number
chat_id: string
}
interface Version {
id: number
version: string
}
interface VersionDto {}
export interface User {
id: number
email: string
token?: string
description?: string
is_admin?: boolean
}
export interface Chat {
id: string
type_id: number
name: string
users: { user_id: number; is_admin?: boolean }[]
}
interface Message {
id: number
user_id: number
text?: string
image: string
video: string
file: string
}
interface Chat {
id: string
type_id: number
users: User[]
image?: string
video?: string
file?: string
created_at: string
updated_at: string
}
interface Response<T> {
data: T
}
enum Services {
getVersion = 'getVersion',
createUser = 'createUser',
getUserByEmail = 'getUserByEmail',
listUser = 'listUser',
listChat = 'listChat',
listMessage = 'listMessage',
createMessage = 'createMessage',
interface Services {
createUser: (data: CreateUserDto) => { data: User }
updateUser: (data: UpdateUserDto) => { data: User }
getUserByToken: (data: GetUserByTokenDto) => { data: User }
getUserByEmail: (data: GetUserByEmailDto) => { data: User }
listUser: (data: ListUserDto) => { data: User[] }
createChat: (data: CreateChatDto) => { data: Chat }
updateChat: (data: UpdateChat) => { data: Chat }
getChat: (data: GetChatDto) => { data: Chat }
listChat: (data: ListChatDto) => { data: Chat[] }
createMessage: (data: CreateMessageDto) => { data: Message }
updateMessage: (data: UpdateMessageDto) => { data: Message }
getMessage: (data: GetMessageDto) => { data: Message }
listMessage: (data: ListMessageDto) => { data: Message[] }
getVersion: (data: VersionDto) => { data: Version }
}
enum ServiceName {
CreateUser = 'createUser',
UpdateUser = 'updateUser',
GetUserByToken = 'getUserByToken',
GetUserByEmail = 'getUserByEmail',
ListUser = 'listUser',
CreateChat = 'createChat',
UpdateChat = 'updateChat',
GetChat = 'getChat',
ListChat = 'listChat',
CreateMessage = 'createMessage',
UpdateMessage = 'updateMessage',
GetMessage = 'getMessage',
ListMessage = 'listMessage',
GetVersion = 'getVersion',
}
class GrpcClient {
messageClient: any
messageClient: Services
constructor() {
console.log('Grpc Client init')
const PROTO_PATH = path.resolve('./proto/message.proto')
console.log('PROTO_PATH', PROTO_PATH)
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
@@ -93,10 +165,12 @@ class GrpcClient {
this.messageClient = new messageProto.MessageService('localhost:8070', grpc.credentials.createInsecure())
}
private toPromise<T, R>(client: any, methodName: Services) {
private toPromise<T, R>(client: any, methodName: ServiceName) {
const service = client[methodName]
return (request: T): Promise<Response<R>> => {
return new Promise((resolve, reject) => {
client[methodName](request, (error: Error, response: Response<R>) => {
service(request, (error: Error, response: Response<R>) => {
if (error) reject(error.message)
else resolve(response)
})
@@ -105,23 +179,25 @@ class GrpcClient {
}
getVersion(dto: VersionDto) {
return this.toPromise<VersionDto, Version>(this.messageClient, Services.getVersion)(dto)
const service = this.messageClient[ServiceName.GetVersion]
return this.toPromise<VersionDto, Version>(this.messageClient, ServiceName.GetVersion)(dto)
}
getUserByEmail(dto: GetUserByEmail) {
return this.toPromise<GetUserByEmail, User>(this.messageClient, Services.getUserByEmail)(dto)
}
// getUserByEmail(dto: GetUserByEmail) {
// return this.toPromise<GetUserByEmail, User>(this.messageClient, ServiceName.GetUserByEmail)(dto)
// }
getChatsByUser(dto: ListChatDto) {
return this.toPromise<ListChatDto, Chat[]>(this.messageClient, Services.listChat)(dto)
return this.toPromise<ListChatDto, Chat[]>(this.messageClient, ServiceName.ListChat)(dto)
}
getMessagesByChatId(dto: ListMessageDto) {
return this.toPromise<ListMessageDto, Message[]>(this.messageClient, Services.listMessage)(dto)
return this.toPromise<ListMessageDto, Message[]>(this.messageClient, ServiceName.ListMessage)(dto)
}
createMessage(dto: CreateMessageDto) {
return this.toPromise<CreateMessageDto, Message>(this.messageClient, Services.createMessage)(dto)
return this.toPromise<CreateMessageDto, Message>(this.messageClient, ServiceName.CreateMessage)(dto)
}
}

View File

@@ -49,10 +49,10 @@ export async function login(req: Request) {
}
export async function upgrade(req: Request, server: Bun.Server<WebSocketData>) {
const userId = await checkRequest(req)
if (!userId) return new Response('Invalid token', { status: HttpStatusCodes.NOT_FOUND })
const payload = await checkRequest(req)
if (!payload) return new Response('Invalid token', { status: HttpStatusCodes.NOT_FOUND })
const success = server.upgrade(req, { data: { userId: userId } })
const success = server.upgrade(req, { data: { userId: +payload.sub, email: payload.email } })
if (success) return undefined
return new Response('Upgrade failed', { status: HttpStatusCodes.BAD_REQUEST })
}
@@ -63,11 +63,7 @@ async function checkRequest(req: Request) {
const token = url.searchParams.get('token')
if (!token) return null
const payload = await verifyAccessToken(token)
console.log('token', token)
console.log(payload)
return +payload.sub
return await verifyAccessToken(token)
} catch (error) {
if (error instanceof errors.JWTInvalid) {
console.log('invalid')

View File

@@ -24,13 +24,15 @@ const server = Bun.serve({
async open(ws) {
try {
const ipAddr = ws.remoteAddress
console.log('ipAddr', ipAddr)
// console.log('ipAddr', ipAddr)
const user = ws.data
const chatResponse = await client.getChatsByUser({ page: 0, user_ids: [1] })
chatResponse.data.forEach((el) => ws.subscribe(el.id))
console.log('chats', chatResponse.data)
console.log('subscriptions', ws.subscriptions)
// console.log('chats', chatResponse.data)
// console.log('subscriptions', ws.subscriptions)
ws.send(JSON.stringify({ type: 'CHATS', ...chatResponse }))
} catch (error) {
@@ -57,7 +59,7 @@ const server = Bun.serve({
return
}
if (o.type === 'CREATE_MESSAGE') {
if (o.type === 'MESSAGE_CREATE') {
console.log('create')
const message = await client.createMessage({
chat_id: o.data.chat_id,
@@ -69,7 +71,7 @@ const server = Bun.serve({
}
if (o.type === 'GET_MESSAGES') {
console.log('get')
console.log('GET_MESSAGES')
const messages = await client.getMessagesByChatId({ chat_id: o.data.chat_id, page: 1 })
server.publish(o.data.chat_id, JSON.stringify({ type: 'MESSAGES', ...messages }))
}

View File

@@ -2,6 +2,18 @@ export interface WebSocketData {
chatId?: string
token?: string
userId: number
email: string
}
export enum DATATYPE {
CHATS_LIST = 'CHATS_LIST',
CHATS_CREATE = 'CHATS_CREATE',
USERS_LIST = 'USERS_LIST',
USER_GET = 'USER_GET',
MESSAGES_LIST = 'MESSAGES_LIST',
MESSAGE_CREATE = 'MESSAGE_CREATE',
STATUS = 'STATUS',
ERROR = 'ERROR',
}
export type LoginDto = { email: string }
@@ -14,7 +26,7 @@ interface ListMessages {
}
interface CreateMessage {
type: 'CREATE_MESSAGE'
type: 'MESSAGE_CREATE'
data: {
chat_id: string
text: string
@@ -32,4 +44,4 @@ interface MessageData {
text: string
}
export type WsData = ListMessages|CreateMessage
export type WsData = ListMessages | CreateMessage