wip
This commit is contained in:
@@ -14,6 +14,7 @@ service MessageService {
|
||||
rpc GetUserByToken(GetUserByTokenRequest) returns(GetUserResponse);
|
||||
rpc GetUserByEmail(GetUserByEmailRequest) returns(GetUserResponse);
|
||||
rpc ListUser(ListUserRequest) returns(ListUserResponse);
|
||||
rpc GetUser(GetUserRequest) returns(GetUserResponse);
|
||||
|
||||
rpc CreateChat(CreateChatRequest) returns(CreateChatResponse);
|
||||
rpc UpdateChat(UpdateChatRequest) returns(UpdateChatResponse);
|
||||
@@ -31,7 +32,10 @@ service MessageService {
|
||||
// User
|
||||
message CreateUserRequest {
|
||||
string email = 1 [(validate.rules).string.email = true];
|
||||
optional string name = 2;
|
||||
optional string name = 2 [(validate.rules).string = {
|
||||
ignore_empty: true, // ⭐ Главное правило
|
||||
max_len: 200
|
||||
}];
|
||||
}
|
||||
|
||||
message CreateUserResponse {
|
||||
@@ -41,7 +45,10 @@ message CreateUserResponse {
|
||||
message UpdateUserRequest {
|
||||
int32 id = 1 [(validate.rules).int32.gt = 0];
|
||||
optional string token = 2; // todo
|
||||
optional string description = 3;
|
||||
optional string description = 3 [(validate.rules).string = {
|
||||
ignore_empty: true,
|
||||
max_len: 200
|
||||
}];
|
||||
}
|
||||
|
||||
message UpdateUserResponse {
|
||||
@@ -56,6 +63,10 @@ message GetUserByEmailRequest {
|
||||
string email = 1 [(validate.rules).string.email = true];
|
||||
}
|
||||
|
||||
message GetUserRequest {
|
||||
int32 id = 1 [(validate.rules).int32.gt = 0];
|
||||
}
|
||||
|
||||
message GetUserResponse {
|
||||
User data = 1;
|
||||
}
|
||||
@@ -91,11 +102,13 @@ message UserForChatResponse {
|
||||
// Chat
|
||||
message CreateChatRequest {
|
||||
optional string name = 1;
|
||||
repeated UserForChat users = 2;
|
||||
repeated UserForChat users = 2 [(validate.rules).repeated = {
|
||||
min_items: 1,
|
||||
}];
|
||||
}
|
||||
|
||||
message UserForChat {
|
||||
int32 user_id = 1;
|
||||
int32 user_id = 1 [(validate.rules).int32.gt = 0];
|
||||
optional bool is_admin = 2;
|
||||
}
|
||||
|
||||
@@ -105,11 +118,11 @@ message CreateChatResponse {
|
||||
|
||||
message UpdateChatRequest {
|
||||
string id = 1 [(validate.rules).string = {
|
||||
pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
|
||||
min_len: 36,
|
||||
max_len: 36
|
||||
uuid: true,
|
||||
}];
|
||||
repeated UserForChat users = 2 [(validate.rules).repeated = {
|
||||
min_items: 1,
|
||||
}];
|
||||
repeated UserForChat users = 2;
|
||||
}
|
||||
|
||||
message UpdateChatResponse {
|
||||
@@ -117,7 +130,9 @@ message UpdateChatResponse {
|
||||
}
|
||||
|
||||
message GetChatRequest {
|
||||
string id = 1;
|
||||
string id = 1 [(validate.rules).string = {
|
||||
uuid: true,
|
||||
}];
|
||||
}
|
||||
|
||||
message GetChatResponse {
|
||||
@@ -144,15 +159,25 @@ message Chat {
|
||||
// Message
|
||||
message CreateMessageRequest {
|
||||
string chat_id = 2 [(validate.rules).string = {
|
||||
pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
|
||||
min_len: 36,
|
||||
max_len: 36
|
||||
uuid: true,
|
||||
}];
|
||||
int32 user_id = 3 [(validate.rules).int32.gt = 0];
|
||||
optional string text = 4;
|
||||
optional string image = 5;
|
||||
optional string video = 6;
|
||||
optional string file = 7;
|
||||
optional string text = 4 [(validate.rules).string = {
|
||||
ignore_empty: true,
|
||||
max_len: 200
|
||||
}];
|
||||
optional string image = 5 [(validate.rules).string = {
|
||||
ignore_empty: true,
|
||||
max_len: 200
|
||||
}];
|
||||
optional string video = 6 [(validate.rules).string = {
|
||||
ignore_empty: true,
|
||||
max_len: 200
|
||||
}];
|
||||
optional string file = 7 [(validate.rules).string = {
|
||||
ignore_empty: true,
|
||||
max_len: 200
|
||||
}];
|
||||
}
|
||||
|
||||
message CreateMessageResponse {
|
||||
@@ -162,14 +187,24 @@ message CreateMessageResponse {
|
||||
message UpdateMessageRequest {
|
||||
int32 id = 1 [(validate.rules).int32.gt = 0];
|
||||
string chat_id = 2 [(validate.rules).string = {
|
||||
pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
|
||||
min_len: 36,
|
||||
max_len: 36
|
||||
uuid: true,
|
||||
}];
|
||||
optional string text = 3 [(validate.rules).string = {
|
||||
ignore_empty: true,
|
||||
max_len: 200
|
||||
}];
|
||||
optional string image = 4 [(validate.rules).string = {
|
||||
ignore_empty: true,
|
||||
max_len: 200
|
||||
}];
|
||||
optional string video = 5 [(validate.rules).string = {
|
||||
ignore_empty: true,
|
||||
max_len: 200
|
||||
}];
|
||||
optional string file = 6 [(validate.rules).string = {
|
||||
ignore_empty: true,
|
||||
max_len: 200
|
||||
}];
|
||||
optional string text = 3;
|
||||
optional string image = 4;
|
||||
optional string video = 5;
|
||||
optional string file = 6;
|
||||
}
|
||||
|
||||
message UpdateMessageResponse {
|
||||
@@ -187,9 +222,7 @@ message GetMessageResponse {
|
||||
message ListMessageRequest {
|
||||
int32 page = 1;
|
||||
string chat_id = 2 [(validate.rules).string = {
|
||||
pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
|
||||
min_len: 36,
|
||||
max_len: 36
|
||||
uuid: true,
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ interface GetUserByEmailDto {
|
||||
email: string
|
||||
}
|
||||
|
||||
interface GetUserByIDDto {
|
||||
id: number
|
||||
}
|
||||
|
||||
interface ListUserDto {
|
||||
page: number
|
||||
iser_ids: number[]
|
||||
@@ -32,7 +36,7 @@ interface CreateChatDto {
|
||||
users: { user_id: number; is_admin?: boolean }[]
|
||||
}
|
||||
|
||||
interface UpdateChat {
|
||||
interface UpdateChatDto {
|
||||
id: number
|
||||
users: { user_id: number; is_admin?: boolean }[]
|
||||
}
|
||||
@@ -70,11 +74,6 @@ interface ListMessageDto {
|
||||
chat_id: string
|
||||
}
|
||||
|
||||
interface Version {
|
||||
id: number
|
||||
version: string
|
||||
}
|
||||
|
||||
interface VersionDto {}
|
||||
|
||||
export interface User {
|
||||
@@ -103,53 +102,38 @@ interface Message {
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
interface Response<T> {
|
||||
data: T
|
||||
interface Version {
|
||||
id: number
|
||||
version: string
|
||||
}
|
||||
|
||||
interface Callback<T> {
|
||||
(error: Error, res: { data: T }): void
|
||||
}
|
||||
|
||||
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',
|
||||
createUser: (data: CreateUserDto, cb: Callback<User>) => void
|
||||
updateUser: (data: UpdateUserDto, cb: Callback<User>) => void
|
||||
getUserByToken: (data: GetUserByTokenDto, cb: Callback<User>) => void
|
||||
getUserByEmail: (data: GetUserByEmailDto, cb: Callback<User>) => void
|
||||
getUser: (data: GetUserByIDDto, cb: Callback<User>) => void
|
||||
listUser: (data: ListUserDto, cb: Callback<User[]>) => void
|
||||
createChat: (data: CreateChatDto, cb: Callback<Chat>) => void
|
||||
updateChat: (data: UpdateChatDto, cb: Callback<Chat>) => void
|
||||
getChat: (data: GetChatDto, cb: Callback<Chat>) => void
|
||||
listChat: (data: ListChatDto, cb: Callback<Chat[]>) => void
|
||||
createMessage: (data: CreateMessageDto, cb: Callback<Message>) => void
|
||||
updateMessage: (data: UpdateMessageDto, cb: Callback<Message>) => void
|
||||
getMessage: (data: GetMessageDto, cb: Callback<Message>) => void
|
||||
listMessage: (data: ListMessageDto, cb: Callback<Message[]>) => void
|
||||
getVersion: (data: VersionDto, cb: Callback<Version>) => void
|
||||
}
|
||||
|
||||
class GrpcClient {
|
||||
messageClient: Services
|
||||
private messageClient: Services
|
||||
|
||||
constructor() {
|
||||
console.log('Grpc Client init')
|
||||
|
||||
const PROTO_PATH = path.resolve('./proto/message.proto')
|
||||
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
|
||||
keepCase: true,
|
||||
@@ -161,43 +145,147 @@ class GrpcClient {
|
||||
|
||||
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition)
|
||||
const messageProto = protoDescriptor.message as any
|
||||
|
||||
this.messageClient = new messageProto.MessageService('localhost:8070', grpc.credentials.createInsecure())
|
||||
// console.log(this.messageClient)
|
||||
}
|
||||
|
||||
private toPromise<T, R>(client: any, methodName: ServiceName) {
|
||||
const service = client[methodName]
|
||||
|
||||
return (request: T): Promise<Response<R>> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
service(request, (error: Error, response: Response<R>) => {
|
||||
if (error) reject(error.message)
|
||||
else resolve(response)
|
||||
})
|
||||
// User
|
||||
createUser(dto: CreateUserDto): Promise<{ data: User }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.createUser(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getVersion(dto: VersionDto) {
|
||||
const service = this.messageClient[ServiceName.GetVersion]
|
||||
|
||||
return this.toPromise<VersionDto, Version>(this.messageClient, ServiceName.GetVersion)(dto)
|
||||
updateUser(dto: UpdateUserDto): Promise<{ data: User }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.updateUser(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// getUserByEmail(dto: GetUserByEmail) {
|
||||
// return this.toPromise<GetUserByEmail, User>(this.messageClient, ServiceName.GetUserByEmail)(dto)
|
||||
// }
|
||||
|
||||
getChatsByUser(dto: ListChatDto) {
|
||||
return this.toPromise<ListChatDto, Chat[]>(this.messageClient, ServiceName.ListChat)(dto)
|
||||
getUserByToken(dto: GetUserByTokenDto): Promise<{ data: User }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.getUserByToken(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getMessagesByChatId(dto: ListMessageDto) {
|
||||
return this.toPromise<ListMessageDto, Message[]>(this.messageClient, ServiceName.ListMessage)(dto)
|
||||
getUserByEmail(dto: GetUserByEmailDto): Promise<{ data: User }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.getUserByEmail(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
createMessage(dto: CreateMessageDto) {
|
||||
return this.toPromise<CreateMessageDto, Message>(this.messageClient, ServiceName.CreateMessage)(dto)
|
||||
getUser(dto: GetUserByIDDto): Promise<{ data: User }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.getUser(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
listUser(dto: ListUserDto): Promise<{ data: User[] }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.listUser(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Chat
|
||||
createChat(dto: CreateChatDto): Promise<{ data: Chat }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.createChat(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
updateChat(dto: UpdateChatDto): Promise<{ data: Chat }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.updateChat(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getChat(dto: GetChatDto): Promise<{ data: Chat }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.getChat(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
listChat(dto: ListChatDto): Promise<{ data: Chat[] }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.listChat(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// message
|
||||
createMessage(dto: CreateMessageDto): Promise<{ data: Message }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.createMessage(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
updateMessage(dto: UpdateMessageDto): Promise<{ data: Message }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.updateMessage(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getMessage(dto: GetMessageDto): Promise<{ data: Message }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.getMessage(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
listMessage(dto: ListMessageDto): Promise<{ data: Message[] }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.listMessage(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// version
|
||||
getVersion(dto: VersionDto): Promise<{ data: Version }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.messageClient.getVersion(dto, (error, data) => {
|
||||
if (error) reject(error?.message)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,34 +2,35 @@ import { HttpStatusCodes } from './constants.ts'
|
||||
import { errors } from 'jose'
|
||||
import type { LoginDto, WebSocketData } from './types/types.ts'
|
||||
import { createAccessToken, verifyAccessToken } from './utils/jwt.ts'
|
||||
import { grpcClient } from './grpc/client.ts'
|
||||
import { grpcClient as client } from './grpc/client.ts'
|
||||
import { config } from './config.ts'
|
||||
|
||||
export async function login(req: Request) {
|
||||
try {
|
||||
const body: LoginDto = await req.json()
|
||||
|
||||
const versionResponse = await grpcClient.getVersion({})
|
||||
console.log(versionResponse.data)
|
||||
const versionResponse = await client.getVersion({})
|
||||
console.log(versionResponse?.data)
|
||||
|
||||
const { email } = body
|
||||
if (!email) return Response.json({ message: 'email required' }, { status: HttpStatusCodes.BAD_REQUEST })
|
||||
|
||||
const userResponse = await grpcClient.getUserByEmail({ email: 'vadim.olonin@gmail.com' })
|
||||
const userResponse = await client.getUserByEmail({ email: body.email })
|
||||
const user = userResponse.data
|
||||
|
||||
if (!user) return Response.json({ message: 'Invalid email or password' }, { status: HttpStatusCodes.NOT_FOUND })
|
||||
|
||||
const accessToken = await createAccessToken(user.id, user.email)
|
||||
|
||||
const expires = new Date(Date.now() + config.cookieExpiry * 1000)
|
||||
const sessionCookie = new Bun.Cookie('token', accessToken.token, {
|
||||
path: '/',
|
||||
expires: expires,
|
||||
// maxAge: config.cookieExpiry,
|
||||
httpOnly: true,
|
||||
// secure: true,
|
||||
sameSite: 'strict',
|
||||
})
|
||||
// const sessionCookie = new Bun.Cookie('token', accessToken.token, {
|
||||
// path: '/',
|
||||
// expires: expires,
|
||||
// maxAge: config.cookieExpiry,
|
||||
// httpOnly: true,
|
||||
// secure: true,
|
||||
// sameSite: 'strict',
|
||||
// })
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
|
||||
18
src/index.ts
18
src/index.ts
@@ -3,7 +3,6 @@ import type { WebSocketData, WsData } from './types/types.ts'
|
||||
import { grpcClient as client } from './grpc/client.ts'
|
||||
import { login, upgrade } from './handles.ts'
|
||||
|
||||
const GROUP = 'group'
|
||||
const PORT = 3000
|
||||
|
||||
const server = Bun.serve({
|
||||
@@ -28,12 +27,11 @@ const server = Bun.serve({
|
||||
|
||||
const user = ws.data
|
||||
|
||||
const chatResponse = await client.getChatsByUser({ page: 0, user_ids: [1] })
|
||||
const userResponse = await client.getUser({ id: user.userId })
|
||||
ws.send(JSON.stringify({ type: 'USER', ...userResponse }))
|
||||
|
||||
const chatResponse = await client.listChat({ page: 0, user_id: user.userId })
|
||||
chatResponse.data.forEach((el) => ws.subscribe(el.id))
|
||||
|
||||
// console.log('chats', chatResponse.data)
|
||||
// console.log('subscriptions', ws.subscriptions)
|
||||
|
||||
ws.send(JSON.stringify({ type: 'CHATS', ...chatResponse }))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
@@ -59,20 +57,20 @@ const server = Bun.serve({
|
||||
return
|
||||
}
|
||||
|
||||
if (o.type === 'MESSAGE_CREATE') {
|
||||
if (o.type === 'CREATE_MESSAGE') {
|
||||
console.log('create')
|
||||
const message = await client.createMessage({
|
||||
const messageResponse = await client.createMessage({
|
||||
chat_id: o.data.chat_id,
|
||||
user_id: ws.data.userId,
|
||||
text: o.data.text,
|
||||
})
|
||||
|
||||
server.publish(o.data.chat_id, JSON.stringify({ type: 'CREATE_MESSAGE', ...message }))
|
||||
server.publish(o.data.chat_id, JSON.stringify({ type: 'MESSAGE', ...messageResponse }))
|
||||
}
|
||||
|
||||
if (o.type === 'GET_MESSAGES') {
|
||||
console.log('GET_MESSAGES')
|
||||
const messages = await client.getMessagesByChatId({ chat_id: o.data.chat_id, page: 1 })
|
||||
const messages = await client.listMessage({ chat_id: o.data.chat_id, page: 1 })
|
||||
server.publish(o.data.chat_id, JSON.stringify({ type: 'MESSAGES', ...messages }))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ interface ListMessages {
|
||||
}
|
||||
|
||||
interface CreateMessage {
|
||||
type: 'MESSAGE_CREATE'
|
||||
type: 'CREATE_MESSAGE'
|
||||
data: {
|
||||
chat_id: string
|
||||
text: string
|
||||
|
||||
Reference in New Issue
Block a user