From ad0751dec865d97dae10464baf79cb6078216fdb Mon Sep 17 00:00:00 2001 From: Aseer KT Date: Sat, 17 Aug 2024 17:00:47 +0530 Subject: [PATCH] chore: use common package to share socket interface --- common/package.json | 7 ++++ common/socket/index.ts | 1 + .../socket/interface.ts | 6 +-- common/tables/base.ts | 11 +++++ .../tables/groups.table.ts | 4 +- common/tables/index.ts | 5 +++ .../tables/members.table.ts | 6 +-- common/tables/message-recipients.table.ts | 23 +++++++++++ .../tables/messages.table.ts | 26 ++---------- .../tables/users.table.ts | 2 +- pnpm-lock.yaml | 26 +++++++++--- pnpm-workspace.prod.yaml | 3 +- pnpm-workspace.yaml | 1 + server/drizzle.config.ts | 2 +- server/package.json | 3 +- server/src/database/constants.ts | 13 ------ server/src/database/helpers.ts | 3 +- server/src/index.ts | 12 +++--- server/src/middlewares.ts | 2 +- .../src/modules/groups/groups.controller.ts | 16 ++++---- server/src/modules/groups/groups.service.ts | 2 +- .../src/modules/members/members.controller.ts | 5 +-- server/src/modules/members/members.service.ts | 10 ++--- .../modules/messages/messages.controller.ts | 9 +++-- .../src/modules/messages/messages.service.ts | 9 +++-- server/src/modules/users/users.controller.ts | 2 +- server/src/redis/handlers.ts | 4 +- server/src/scripts/seed.ts | 14 +++++-- server/src/socket/events.ts | 5 +-- web/package.json | 3 +- web/src/features/group/group.interface.ts | 8 ++-- .../message/components/MessageItem.tsx | 2 +- web/src/features/message/message.interface.ts | 10 ++--- web/src/interfaces/socket.interface.ts | 40 +------------------ web/src/utils/socket.ts | 2 +- 35 files changed, 151 insertions(+), 146 deletions(-) create mode 100644 common/package.json create mode 100644 common/socket/index.ts rename server/src/socket/socket.interface.ts => common/socket/interface.ts (90%) create mode 100644 common/tables/base.ts rename server/src/modules/groups/groups.schema.ts => common/tables/groups.table.ts (78%) create mode 100644 common/tables/index.ts rename server/src/modules/members/members.schema.ts => common/tables/members.table.ts (86%) create mode 100644 common/tables/message-recipients.table.ts rename server/src/modules/messages/messages.schema.ts => common/tables/messages.table.ts (60%) rename server/src/modules/users/users.schema.ts => common/tables/users.table.ts (91%) diff --git a/common/package.json b/common/package.json new file mode 100644 index 0000000..06bca56 --- /dev/null +++ b/common/package.json @@ -0,0 +1,7 @@ +{ + "name": "common", + "version": "1.0.0", + "dependencies": { + "drizzle-orm": "^0.31.2" + } +} \ No newline at end of file diff --git a/common/socket/index.ts b/common/socket/index.ts new file mode 100644 index 0000000..c50ad02 --- /dev/null +++ b/common/socket/index.ts @@ -0,0 +1 @@ +export * from './interface' diff --git a/server/src/socket/socket.interface.ts b/common/socket/interface.ts similarity index 90% rename from server/src/socket/socket.interface.ts rename to common/socket/interface.ts index 5365ad4..9d5f302 100644 --- a/server/src/socket/socket.interface.ts +++ b/common/socket/interface.ts @@ -1,7 +1,7 @@ -import { Group } from '@/modules/groups/groups.schema' -import { Member } from '@/modules/members/members.schema' -import { Message } from '@/modules/messages/messages.schema' import { Server, Socket } from 'socket.io' +import { Group } from '../tables/groups.table' +import { Member } from '../tables/members.table' +import { Message } from '../tables/messages.table' export type ChatMode = 'group' | 'direct' diff --git a/common/tables/base.ts b/common/tables/base.ts new file mode 100644 index 0000000..be9bfbb --- /dev/null +++ b/common/tables/base.ts @@ -0,0 +1,11 @@ +import { bigserial, timestamp } from 'drizzle-orm/pg-core' + +export const baseSchema = { + id: bigserial('id', { mode: 'number' }).primaryKey(), + createdAt: timestamp('created_at', { withTimezone: true }) + .notNull() + .defaultNow(), + updatedAt: timestamp('updated_at', { withTimezone: true }) + .defaultNow() + .$onUpdate(() => new Date()), +} diff --git a/server/src/modules/groups/groups.schema.ts b/common/tables/groups.table.ts similarity index 78% rename from server/src/modules/groups/groups.schema.ts rename to common/tables/groups.table.ts index 08d6b56..f4dfcc7 100644 --- a/server/src/modules/groups/groups.schema.ts +++ b/common/tables/groups.table.ts @@ -1,6 +1,6 @@ -import { baseSchema } from '@/database/constants' -import { usersTable } from '@/modules/users/users.schema' import { bigint, pgTable, varchar } from 'drizzle-orm/pg-core' +import { baseSchema } from './base' +import { usersTable } from './users.table' export const groupsTable = pgTable('groups', { ...baseSchema, diff --git a/common/tables/index.ts b/common/tables/index.ts new file mode 100644 index 0000000..90b90dd --- /dev/null +++ b/common/tables/index.ts @@ -0,0 +1,5 @@ +export * from './groups.table' +export * from './members.table' +export * from './message-recipients.table' +export * from './messages.table' +export * from './users.table' diff --git a/server/src/modules/members/members.schema.ts b/common/tables/members.table.ts similarity index 86% rename from server/src/modules/members/members.schema.ts rename to common/tables/members.table.ts index b25ce06..e3a27e5 100644 --- a/server/src/modules/members/members.schema.ts +++ b/common/tables/members.table.ts @@ -1,7 +1,7 @@ -import { baseSchema } from '@/database/constants' import { bigint, index, pgEnum, pgTable, unique } from 'drizzle-orm/pg-core' -import { groupsTable } from '../groups/groups.schema' -import { usersTable } from '../users/users.schema' +import { baseSchema } from './base' +import { groupsTable } from './groups.table' +import { usersTable } from './users.table' // order of roles shows auth precedence export const memberRoleEnum = pgEnum('member_role', [ diff --git a/common/tables/message-recipients.table.ts b/common/tables/message-recipients.table.ts new file mode 100644 index 0000000..72bc0f7 --- /dev/null +++ b/common/tables/message-recipients.table.ts @@ -0,0 +1,23 @@ +import { bigint, pgTable, unique } from 'drizzle-orm/pg-core' +import { baseSchema } from './base' +import { messagesTable } from './messages.table' +import { usersTable } from './users.table' + +export const messageRecipientsTable = pgTable( + 'message_recipients', + { + ...baseSchema, + messageId: bigint('message_id', { mode: 'number' }) + .references(() => messagesTable.id, { onDelete: 'cascade' }) + .notNull(), + recipientId: bigint('recipient_id', { mode: 'number' }) + .references(() => usersTable.id) + .notNull(), + }, + table => ({ + uniqueMessageRecipientIndex: unique().on( + table.messageId, + table.recipientId, + ), + }), +) diff --git a/server/src/modules/messages/messages.schema.ts b/common/tables/messages.table.ts similarity index 60% rename from server/src/modules/messages/messages.schema.ts rename to common/tables/messages.table.ts index b616046..47420af 100644 --- a/server/src/modules/messages/messages.schema.ts +++ b/common/tables/messages.table.ts @@ -1,4 +1,3 @@ -import { baseSchema } from '@/database/constants' import { AnyPgColumn, bigint, @@ -6,10 +5,10 @@ import { index, pgTable, text, - unique, } from 'drizzle-orm/pg-core' -import { groupsTable } from '../groups/groups.schema' -import { usersTable } from '../users/users.schema' +import { baseSchema } from './base' +import { groupsTable } from './groups.table' +import { usersTable } from './users.table' export const messagesTable = pgTable( 'messages', @@ -37,24 +36,5 @@ export const messagesTable = pgTable( }), ) -export const messageRecipientsTable = pgTable( - 'message_recipients', - { - ...baseSchema, - messageId: bigint('message_id', { mode: 'number' }) - .references(() => messagesTable.id, { onDelete: 'cascade' }) - .notNull(), - recipientId: bigint('recipient_id', { mode: 'number' }) - .references(() => usersTable.id) - .notNull(), - }, - table => ({ - uniqueMessageRecipientIndex: unique().on( - table.messageId, - table.recipientId, - ), - }), -) - export type Message = typeof messagesTable.$inferSelect export type NewMessage = typeof messagesTable.$inferInsert diff --git a/server/src/modules/users/users.schema.ts b/common/tables/users.table.ts similarity index 91% rename from server/src/modules/users/users.schema.ts rename to common/tables/users.table.ts index 799c2d6..b7b1f9d 100644 --- a/server/src/modules/users/users.schema.ts +++ b/common/tables/users.table.ts @@ -1,6 +1,6 @@ -import { baseSchema } from '@/database/constants' import { sql } from 'drizzle-orm' import { pgTable, timestamp, varchar } from 'drizzle-orm/pg-core' +import { baseSchema } from './base' export const usersTable = pgTable('users', { ...baseSchema, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index feee379..207d30b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,6 +21,12 @@ importers: specifier: ^5.5.4 version: 5.5.4 + common: + dependencies: + drizzle-orm: + specifier: ^0.31.2 + version: 0.31.2(@types/pg@8.11.6)(@types/react@18.3.3)(pg@8.12.0)(react@18.3.1) + e2e: devDependencies: '@faker-js/faker': @@ -53,6 +59,9 @@ importers: colors: specifier: ^1.4.0 version: 1.4.0 + common: + specifier: workspace:* + version: link:../common cookie-parser: specifier: ^1.4.6 version: 1.4.6 @@ -168,6 +177,9 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 + common: + specifier: workspace:* + version: link:../common cva: specifier: npm:class-variance-authority@^0.7.0 version: class-variance-authority@0.7.0 @@ -252,7 +264,7 @@ importers: version: 5.12.0(rollup@2.79.1) tailwindcss: specifier: ^3.4.4 - version: 3.4.4(ts-node@10.9.1(@types/node@20.14.5)(typescript@5.4.5)) + version: 3.4.4(ts-node@10.9.1(@swc/core@1.6.3(@swc/helpers@0.5.11))(@types/node@20.14.5)(typescript@5.4.5)) typescript: specifier: ^5.2.2 version: 5.4.5 @@ -8588,13 +8600,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.4.38 - postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.1(@types/node@20.14.5)(typescript@5.4.5)): + postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.1(@swc/core@1.6.3(@swc/helpers@0.5.11))(@types/node@20.14.5)(typescript@5.4.5)): dependencies: lilconfig: 3.1.2 yaml: 2.4.5 optionalDependencies: postcss: 8.4.38 - ts-node: 10.9.1(@types/node@20.14.5)(typescript@5.4.5) + ts-node: 10.9.1(@swc/core@1.6.3(@swc/helpers@0.5.11))(@types/node@20.14.5)(typescript@5.4.5) postcss-nested@6.0.1(postcss@8.4.38): dependencies: @@ -9123,7 +9135,7 @@ snapshots: dependencies: '@babel/runtime': 7.24.7 - tailwindcss@3.4.4(ts-node@10.9.1(@types/node@20.14.5)(typescript@5.4.5)): + tailwindcss@3.4.4(ts-node@10.9.1(@swc/core@1.6.3(@swc/helpers@0.5.11))(@types/node@20.14.5)(typescript@5.4.5)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -9142,7 +9154,7 @@ snapshots: postcss: 8.4.38 postcss-import: 15.1.0(postcss@8.4.38) postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.1(@types/node@20.14.5)(typescript@5.4.5)) + postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.1(@swc/core@1.6.3(@swc/helpers@0.5.11))(@types/node@20.14.5)(typescript@5.4.5)) postcss-nested: 6.0.1(postcss@8.4.38) postcss-selector-parser: 6.1.0 resolve: 1.22.8 @@ -9219,7 +9231,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-node@10.9.1(@types/node@20.14.5)(typescript@5.4.5): + ts-node@10.9.1(@swc/core@1.6.3(@swc/helpers@0.5.11))(@types/node@20.14.5)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -9236,6 +9248,8 @@ snapshots: typescript: 5.4.5 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.6.3(@swc/helpers@0.5.11) optional: true tslib@2.6.3: diff --git a/pnpm-workspace.prod.yaml b/pnpm-workspace.prod.yaml index 2380e05..3f163b0 100644 --- a/pnpm-workspace.prod.yaml +++ b/pnpm-workspace.prod.yaml @@ -1,3 +1,4 @@ packages: - 'web' - - 'server' \ No newline at end of file + - 'server' + - 'common' \ No newline at end of file diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index cc9206f..5d0d2e2 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,5 @@ packages: - 'web' - 'server' + - 'common' - 'e2e' \ No newline at end of file diff --git a/server/drizzle.config.ts b/server/drizzle.config.ts index a93c158..2429769 100644 --- a/server/drizzle.config.ts +++ b/server/drizzle.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from 'drizzle-kit' export default defineConfig({ - schema: './src/modules/**/*.schema.ts', + schema: 'common/tables/index.ts', out: './drizzle', dialect: 'postgresql', dbCredentials: { diff --git a/server/package.json b/server/package.json index 4f98b61..cda593b 100644 --- a/server/package.json +++ b/server/package.json @@ -40,7 +40,8 @@ "socket.io": "^4.7.5", "swagger-autogen": "^2.23.7", "swagger-ui-express": "^5.0.1", - "uuid": "^10.0.0" + "uuid": "^10.0.0", + "common": "workspace:*" }, "devDependencies": { "@eslint/js": "^9.6.0", diff --git a/server/src/database/constants.ts b/server/src/database/constants.ts index b4ffb43..e69de29 100644 --- a/server/src/database/constants.ts +++ b/server/src/database/constants.ts @@ -1,13 +0,0 @@ -import { bigserial, timestamp } from 'drizzle-orm/pg-core' - -export const baseSchema = { - id: bigserial('id', { mode: 'number' }).primaryKey(), - createdAt: timestamp('created_at', { withTimezone: true }) - .notNull() - .defaultNow(), - updatedAt: timestamp('updated_at', { withTimezone: true }) - .defaultNow() - .$onUpdate(() => new Date()), -} - -export const defaultLimit = 15 diff --git a/server/src/database/helpers.ts b/server/src/database/helpers.ts index adfa1d0..29ddc4a 100644 --- a/server/src/database/helpers.ts +++ b/server/src/database/helpers.ts @@ -10,7 +10,8 @@ import { } from 'drizzle-orm' import { PgColumn, PgSelect } from 'drizzle-orm/pg-core' import get from 'lodash/get' -import { defaultLimit } from './constants' + +export const defaultLimit = 15 export const getPaginationParams = ( query: Record, diff --git a/server/src/index.ts b/server/src/index.ts index edecdd7..5313582 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -2,6 +2,12 @@ import './utils/loadModules' import { createAdapter } from '@socket.io/redis-streams-adapter' import 'colors' +import { + ClientToServerEvents, + InterServerEvents, + ServerToClientEvents, + SocketData, +} from 'common/socket' import cookieParser from 'cookie-parser' import cors from 'cors' import { migrate } from 'drizzle-orm/node-postgres/migrator' @@ -19,12 +25,6 @@ import { getRedisClient } from './redis' import rootRouter from './routes' import { registerSocketEvents } from './socket/events' import { socketAuthMiddleware } from './socket/middlewares' -import { - ClientToServerEvents, - InterServerEvents, - ServerToClientEvents, - SocketData, -} from './socket/socket.interface' import swaggerDocument from './swagger-output.json' const createApp = async () => { diff --git a/server/src/middlewares.ts b/server/src/middlewares.ts index 028b800..f5dd265 100644 --- a/server/src/middlewares.ts +++ b/server/src/middlewares.ts @@ -1,6 +1,6 @@ +import { MemberRole } from 'common/tables' import { ErrorRequestHandler, RequestHandler } from 'express' import { config } from './config' -import { MemberRole } from './modules/members/members.schema' import { checkPermission } from './modules/members/members.service' import { badRequest, notAuthenticated, notAuthorized } from './utils/api' import { verifyAccessToken } from './utils/jwt' diff --git a/server/src/modules/groups/groups.controller.ts b/server/src/modules/groups/groups.controller.ts index 4876573..0494add 100644 --- a/server/src/modules/groups/groups.controller.ts +++ b/server/src/modules/groups/groups.controller.ts @@ -8,8 +8,15 @@ import { } from '@/database/helpers' import { deleteGroupRoles, deleteMemberRole } from '@/redis/handlers' import { roomKeys } from '@/socket/helpers' -import { TypedIOServer } from '@/socket/socket.interface' import { badRequest, notAuthorized, notFound } from '@/utils/api' +import { TypedIOServer } from 'common/socket' +import { + groupsTable, + membersTable, + messageRecipientsTable, + messagesTable, + usersTable, +} from 'common/tables' import { and, count, @@ -28,14 +35,7 @@ import { } from 'drizzle-orm' import { union } from 'drizzle-orm/pg-core' import { RequestHandler } from 'express' -import { membersTable } from '../members/members.schema' import { addMembers } from '../members/members.service' -import { - messageRecipientsTable, - messagesTable, -} from '../messages/messages.schema' -import { usersTable } from '../users/users.schema' -import { groupsTable } from './groups.schema' import { handleMemberDelete } from './groups.service' // CREATE diff --git a/server/src/modules/groups/groups.service.ts b/server/src/modules/groups/groups.service.ts index 29ae8b9..c9b6013 100644 --- a/server/src/modules/groups/groups.service.ts +++ b/server/src/modules/groups/groups.service.ts @@ -1,5 +1,5 @@ import { roomKeys } from '@/socket/helpers' -import { TypedIOServer } from '@/socket/socket.interface' +import { TypedIOServer } from 'common/socket' import { Request } from 'express' export const handleMemberDelete = ( diff --git a/server/src/modules/members/members.controller.ts b/server/src/modules/members/members.controller.ts index 39dfd5f..5c43c6d 100644 --- a/server/src/modules/members/members.controller.ts +++ b/server/src/modules/members/members.controller.ts @@ -2,12 +2,11 @@ import { db } from '@/database' import { getPaginationParams, withPagination } from '@/database/helpers' import { checkOnlineUsers, setGroupMemberRoleTxn } from '@/redis/handlers' import { roomKeys } from '@/socket/helpers' -import { TypedIOServer } from '@/socket/socket.interface' import { badRequest, notFound } from '@/utils/api' +import { TypedIOServer } from 'common/socket' +import { MemberRole, membersTable, usersTable } from 'common/tables' import { and, asc, eq, getTableColumns, gt, like } from 'drizzle-orm' import { RequestHandler } from 'express' -import { usersTable } from '../users/users.schema' -import { MemberRole, membersTable } from './members.schema' export const joinRooms: RequestHandler = async (req, res, next) => { try { diff --git a/server/src/modules/members/members.service.ts b/server/src/modules/members/members.service.ts index 244017d..11fdfd1 100644 --- a/server/src/modules/members/members.service.ts +++ b/server/src/modules/members/members.service.ts @@ -1,16 +1,16 @@ import { db } from '@/database' import { getMemberRole, setMemberRolesForAGroup } from '@/redis/handlers' import { roomKeys } from '@/socket/helpers' -import { TypedIOServer } from '@/socket/socket.interface' -import { and, eq } from 'drizzle-orm' -import { NodePgDatabase } from 'drizzle-orm/node-postgres' -import { Group } from '../groups/groups.schema' +import { TypedIOServer } from 'common/socket' import { + Group, MemberRole, NewMember, memberRoles, membersTable, -} from './members.schema' +} from 'common/tables' +import { and, eq } from 'drizzle-orm' +import { NodePgDatabase } from 'drizzle-orm/node-postgres' export const checkPermission = async ( groupId: number, diff --git a/server/src/modules/messages/messages.controller.ts b/server/src/modules/messages/messages.controller.ts index dc92a11..1cd2201 100644 --- a/server/src/modules/messages/messages.controller.ts +++ b/server/src/modules/messages/messages.controller.ts @@ -1,13 +1,16 @@ import { db } from '@/database' import { getPaginationParams, withPagination } from '@/database/helpers' import { roomKeys } from '@/socket/helpers' -import { TypedIOServer } from '@/socket/socket.interface' import { notAuthorized } from '@/utils/api' +import { TypedIOServer } from 'common/socket' +import { + messageRecipientsTable, + messagesTable, + usersTable, +} from 'common/tables' import { and, desc, eq, getTableColumns, isNull, lt, or } from 'drizzle-orm' import { alias } from 'drizzle-orm/pg-core' import { RequestHandler } from 'express' -import { usersTable } from '../users/users.schema' -import { messageRecipientsTable, messagesTable } from './messages.schema' import { checkMessageOwnerShip } from './messages.service' export const listMessages: RequestHandler = async (req, res, next) => { diff --git a/server/src/modules/messages/messages.service.ts b/server/src/modules/messages/messages.service.ts index 5d5deca..b7f6156 100644 --- a/server/src/modules/messages/messages.service.ts +++ b/server/src/modules/messages/messages.service.ts @@ -1,9 +1,12 @@ import { db } from '@/database' +import { + groupsTable, + messageRecipientsTable, + messagesTable, + usersTable, +} from 'common/tables' import { and, eq, getTableColumns, isNull } from 'drizzle-orm' -import { groupsTable } from '../groups/groups.schema' import { checkPermission } from '../members/members.service' -import { usersTable } from '../users/users.schema' -import { messageRecipientsTable, messagesTable } from './messages.schema' export const insertMessage = async ({ groupId, diff --git a/server/src/modules/users/users.controller.ts b/server/src/modules/users/users.controller.ts index 3d4b581..69327f0 100644 --- a/server/src/modules/users/users.controller.ts +++ b/server/src/modules/users/users.controller.ts @@ -3,9 +3,9 @@ import { notFound } from '@/utils/api' import { signTokens } from '@/utils/jwt' import { removeAttrFromObject } from '@/utils/object' import { hash, verify } from 'argon2' +import { usersTable } from 'common/tables' import { and, eq, getTableColumns, like, ne } from 'drizzle-orm' import { RequestHandler } from 'express' -import { usersTable } from './users.schema' export const signUpUser: RequestHandler = async (req, res, next) => { try { diff --git a/server/src/redis/handlers.ts b/server/src/redis/handlers.ts index ab13f45..a22cd97 100644 --- a/server/src/redis/handlers.ts +++ b/server/src/redis/handlers.ts @@ -1,5 +1,5 @@ -import { MemberRole } from '@/modules/members/members.schema' -import { ChatMode } from '@/socket/socket.interface' +import { ChatMode } from 'common/socket' +import { MemberRole } from 'common/tables' import { getRedisClient } from '.' const redisClient = getRedisClient() diff --git a/server/src/scripts/seed.ts b/server/src/scripts/seed.ts index d63e177..f9a3903 100644 --- a/server/src/scripts/seed.ts +++ b/server/src/scripts/seed.ts @@ -1,13 +1,19 @@ import '../utils/loadModules' import { connectDB, db } from '@/database' -import { NewGroup, groupsTable } from '@/modules/groups/groups.schema' -import { NewMember, membersTable } from '@/modules/members/members.schema' -import { NewMessage, messagesTable } from '@/modules/messages/messages.schema' -import { NewUser, usersTable } from '@/modules/users/users.schema' import { faker } from '@faker-js/faker' import { hash } from 'argon2' import 'colors' +import { + NewGroup, + NewMember, + NewMessage, + NewUser, + groupsTable, + membersTable, + messagesTable, + usersTable, +} from 'common/tables' const USER_PASSWORD = 'bob@123' const USER_COUNT = 100 diff --git a/server/src/socket/events.ts b/server/src/socket/events.ts index 95a2dc0..6eec88b 100644 --- a/server/src/socket/events.ts +++ b/server/src/socket/events.ts @@ -1,6 +1,4 @@ import { db } from '@/database' -import { groupsTable } from '@/modules/groups/groups.schema' -import { membersTable } from '@/modules/members/members.schema' import { insertMessage, markChatMessagesAsRead, @@ -13,6 +11,8 @@ import { removeTypingUser, setTypingUser, } from '@/redis/handlers' +import { ChatMode, TypedIOServer, TypedSocket } from 'common/socket' +import { groupsTable, membersTable } from 'common/tables' import { eq } from 'drizzle-orm' import { Socket } from 'socket.io' import { config } from '../config' @@ -21,7 +21,6 @@ import { currentGroupRoomPrefix, roomKeys, } from './helpers' -import { ChatMode, TypedIOServer, TypedSocket } from './socket.interface' function leavePreviousChat(socket: Socket) { const rooms = Array.from(socket.rooms) diff --git a/web/package.json b/web/package.json index ed5c642..a6481af 100644 --- a/web/package.json +++ b/web/package.json @@ -21,7 +21,8 @@ "react-dom": "^18.2.0", "react-router-dom": "^6.23.1", "socket.io-client": "^4.7.5", - "tailwind-merge": "^2.3.0" + "tailwind-merge": "^2.3.0", + "common": "workspace:*" }, "devDependencies": { "@tanstack/eslint-plugin-query": "^5.47.0", diff --git a/web/src/features/group/group.interface.ts b/web/src/features/group/group.interface.ts index 2fc8bdd..028f811 100644 --- a/web/src/features/group/group.interface.ts +++ b/web/src/features/group/group.interface.ts @@ -8,19 +8,19 @@ export interface IGroup { id: number name: string ownerId: number - createdAt: string + createdAt: Date } export interface IChat { - groupId?: number - partnerId?: number + groupId: number | null + partnerId?: number | null chatName: string lastMessage?: { messageId: number content: string } unreadCount: number - lastActivity: string + lastActivity: Date } export type IPaginatedInfiniteChats = InfiniteData> diff --git a/web/src/features/message/components/MessageItem.tsx b/web/src/features/message/components/MessageItem.tsx index 8dedd07..18b7d64 100644 --- a/web/src/features/message/components/MessageItem.tsx +++ b/web/src/features/message/components/MessageItem.tsx @@ -66,7 +66,7 @@ export const MessageItem = forwardRef( )} diff --git a/web/src/features/message/message.interface.ts b/web/src/features/message/message.interface.ts index 9becfd3..382c5f2 100644 --- a/web/src/features/message/message.interface.ts +++ b/web/src/features/message/message.interface.ts @@ -6,14 +6,14 @@ import { InfiniteData } from '@tanstack/react-query' export interface IMessage { id: number - groupId?: number - receiverId?: number + groupId: number | null + receiverId: number | null senderId: number username: string content: string - createdAt: string - isDeleted: boolean - parentMessageId?: number + createdAt: Date + isDeleted: boolean | null + parentMessageId?: number | null parentMessage?: Pick } diff --git a/web/src/interfaces/socket.interface.ts b/web/src/interfaces/socket.interface.ts index 02357db..e3bb445 100644 --- a/web/src/interfaces/socket.interface.ts +++ b/web/src/interfaces/socket.interface.ts @@ -1,42 +1,4 @@ -import { ChatMode } from '@/features/chat/chat.interface' -import { IGroup } from '@/features/group/group.interface' +import { ClientToServerEvents, ServerToClientEvents } from 'common/socket' import { Socket } from 'socket.io-client' -import { IMember } from '../features/member/member.interface' -import { IMessage } from '../features/message/message.interface' - -export interface ServerToClientEvents { - userOnline: (userId: number) => void - userOffline: (userId: number) => void - newMessage: (message: IMessage & { chatName: string }) => void - newMember: (member: IMember) => void - newMembers: (member: IMember[]) => void - memberLeft: (args: { groupId: number; memberId: number }) => void - newGroup: (group: IGroup) => void - groupDeleted: (groupId: number) => void - messageRead: (messageId: number) => void - messageDeleted: (messageId: number) => void - chatMarkedAsRead: (args: { groupId?: number; partnerId?: number }) => void - typingUsers: (users: { id: number; username: string }[]) => void -} - -export interface ClientToServerEvents { - joinGroup: (groupId: number) => void - joinDm: (partnerId: number) => void - createMessage: ( - args: { - groupId?: number - receiverId?: number - text: string - parentMessageId?: number - }, - callback: (response: { message?: IMessage; error?: unknown }) => void, - ) => void - markMessageAsRead: (messageId: number) => void - markChatMessagesAsRead: (args: { - groupId?: number - partnerId?: number - }) => void - typing: (args: { chatId: number; mode: ChatMode; isTyping: boolean }) => void -} export type TypedSocket = Socket diff --git a/web/src/utils/socket.ts b/web/src/utils/socket.ts index 8d2f323..f8f1ac3 100644 --- a/web/src/utils/socket.ts +++ b/web/src/utils/socket.ts @@ -1,7 +1,7 @@ +import { TypedSocket } from '@/interfaces/socket.interface' import { io } from 'socket.io-client' import { config } from '../config' import { toast } from '../hooks/useToast' -import { TypedSocket } from '../interfaces/socket.interface' import { accessToken } from './token' let socket: TypedSocket