Skip to content

Commit

Permalink
Merge pull request #29 from ryo-manba/add-create-chat-room
Browse files Browse the repository at this point in the history
チャットルーム作成機能を実装した
  • Loading branch information
rakushoo committed Oct 27, 2022
2 parents 014b710 + 6c12d98 commit f4bcfb5
Show file tree
Hide file tree
Showing 14 changed files with 500 additions and 40 deletions.
9 changes: 6 additions & 3 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,26 @@
"@nestjs/common": "^9.0.0",
"@nestjs/core": "^9.0.0",
"@nestjs/platform-express": "^9.0.0",
"@prisma/client": "^4.5.0",
"@nestjs/platform-socket.io": "^9.1.6",
"@nestjs/websockets": "^9.1.6",
"@prisma/client": "4.5.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
},
"devDependencies": {
"@nestjs/cli": "^9.0.0",
"@nestjs/platform-socket.io": "^9.1.5",
"@nestjs/platform-socket.io": "^9.1.6",
"@nestjs/schematics": "^9.0.0",
"@nestjs/testing": "^9.0.0",
"@nestjs/websockets": "^9.1.5",
"@nestjs/websockets": "^9.1.6",
"@types/eslint": "^8.4.7",
"@types/eslint-plugin-prettier": "^3.1.0",
"@types/jest": "28.1.8",
"@types/node": "^16.0.0",
"@types/prettier": "^2.7.1",
"@types/rimraf": "^3.0.2",
"@types/socket.io": "^3.0.2",
"@types/source-map-support": "^0.5.6",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.40.1",
Expand Down
26 changes: 26 additions & 0 deletions backend/prisma/migrations/20221025054307_chatroom/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
-- CreateTable
CREATE TABLE "ChatRoom" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"type" BOOLEAN NOT NULL,
"author" TEXT NOT NULL,
"hashedPassword" TEXT NOT NULL,

CONSTRAINT "ChatRoom_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "Message" (
"id" SERIAL NOT NULL,
"roomId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
"message" TEXT NOT NULL,

CONSTRAINT "Message_pkey" PRIMARY KEY ("id")
);

-- AddForeignKey
ALTER TABLE "Message" ADD CONSTRAINT "Message_roomId_fkey" FOREIGN KEY ("roomId") REFERENCES "ChatRoom"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Message" ADD CONSTRAINT "Message_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
27 changes: 23 additions & 4 deletions backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,29 @@ datasource db {
}

model User {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
name String
email String @unique
email String @unique
hashedPassword String
Message Message[]
}

model ChatRoom {
id Int @id @default(autoincrement())
name String
type Boolean // TODO: private or public(DMは別にする?)
author String // 最初は作成者にする -> 後で変更できるようにする
hashedPassword String
message Message[]
}

model Message {
id Int @id @default(autoincrement())
roomId Int
userId Int
message String
chatRoom ChatRoom @relation(fields: [roomId], references: [id], onDelete: Cascade) // Roomが消されたらメッセージも削除される
user User @relation(fields: [userId], references: [id])
}
3 changes: 2 additions & 1 deletion backend/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ChatModule } from './chat/chat.module';
import { GameModule } from './game/game.module';

@Module({
imports: [GameModule],
imports: [ChatModule, GameModule],
controllers: [AppController],
providers: [AppService],
})
Expand Down
18 changes: 18 additions & 0 deletions backend/src/chat/chat.gateway.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ChatGateway } from './chat.gateway';

describe('ChatGateway', () => {
let gateway: ChatGateway;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ChatGateway],
}).compile();

gateway = module.get<ChatGateway>(ChatGateway);
});

it('should be defined', () => {
expect(gateway).toBeDefined();
});
});
37 changes: 37 additions & 0 deletions backend/src/chat/chat.gateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {
MessageBody,
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
} from '@nestjs/websockets';
import { Server } from 'socket.io';
import { Logger } from '@nestjs/common';
import { PrismaService } from '../prisma.service';
import { ChatService } from './chat.service';
import { ChatRoom as ChatRoomModel } from '@prisma/client';

@WebSocketGateway({
cors: {
origin: '*',
},
namespace: '/chat',
})
export class ChatGateway {
constructor(
private prisma: PrismaService,
private readonly chatService: ChatService,
) {}

@WebSocketServer() server: Server;

private logger: Logger = new Logger('ChatGateway');

@SubscribeMessage('room:create')
CreateRoom(@MessageBody() data: ChatRoomModel): void {
this.logger.log(`[DEBUG] room:create': ${data.name}`);
// とりあえずvoidで受ける
void this.chatService.createChatRoom(data);
// 送信者にdataを送り返す
this.server.emit('room:created', data);
}
}
9 changes: 9 additions & 0 deletions backend/src/chat/chat.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { ChatGateway } from './chat.gateway';
import { ChatService } from './chat.service';
import { PrismaService } from '../prisma.service';

@Module({
providers: [ChatGateway, ChatService, PrismaService],
})
export class ChatModule {}
18 changes: 18 additions & 0 deletions backend/src/chat/chat.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ChatService } from './chat.service';

describe('ChatService', () => {
let service: ChatService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ChatService],
}).compile();

service = module.get<ChatService>(ChatService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
60 changes: 60 additions & 0 deletions backend/src/chat/chat.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma.service';
import { ChatRoom, Prisma } from '@prisma/client';

@Injectable()
export class ChatService {
constructor(private prisma: PrismaService) {}

async chatRoom(
charRoomWhereUniqueInput: Prisma.ChatRoomWhereUniqueInput,
): Promise<ChatRoom | null> {
return this.prisma.chatRoom.findUnique({
where: charRoomWhereUniqueInput,
});
}

async chatRooms(params: {
skip?: number;
take?: number;
cursor?: Prisma.ChatRoomWhereUniqueInput;
where?: Prisma.ChatRoomWhereInput;
orderBy?: Prisma.ChatRoomOrderByWithRelationInput;
}): Promise<ChatRoom[]> {
const { skip, take, cursor, where, orderBy } = params;

return this.prisma.chatRoom.findMany({
skip,
take,
cursor,
where,
orderBy,
});
}

async createChatRoom(data: Prisma.ChatRoomCreateInput): Promise<ChatRoom> {
return this.prisma.chatRoom.create({
data,
});
}

async updateChatRoom(params: {
where: Prisma.ChatRoomWhereUniqueInput;
data: Prisma.ChatRoomUpdateInput;
}): Promise<ChatRoom> {
const { where, data } = params;

return this.prisma.chatRoom.update({
data,
where,
});
}

async deleteChatRoom(
where: Prisma.ChatRoomWhereUniqueInput,
): Promise<ChatRoom> {
return this.prisma.chatRoom.delete({
where,
});
}
}
6 changes: 4 additions & 2 deletions backend/src/prisma.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient
implements OnModuleInit, OnModuleDestroy {
export class PrismaService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
async onModuleInit() {
await this.$connect();
}
Expand Down
48 changes: 24 additions & 24 deletions backend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -733,12 +733,12 @@
multer "1.4.4-lts.1"
tslib "2.4.0"

"@nestjs/platform-socket.io@^9.1.5":
version "9.1.5"
resolved "https://registry.yarnpkg.com/@nestjs/platform-socket.io/-/platform-socket.io-9.1.5.tgz#2d39dc72c1f4e28114ad0ada3f35e5b28840159d"
integrity sha512-X45a7xKine5iqRIqxvornI9ikDNfwudTFSXxVIdzt828n4biqgaDPA2M/aId7y31uH0zykFMhXkctdy20944kA==
"@nestjs/platform-socket.io@^9.1.6":
version "9.1.6"
resolved "https://registry.yarnpkg.com/@nestjs/platform-socket.io/-/platform-socket.io-9.1.6.tgz#e0591ffb1d486c6bb7c4fc82188ba6287a5c649e"
integrity sha512-h1cilQaVimA3HjlEQWXidAZ3apaooeH1RTL+yZRZ1Wa/FPybiJCgkfDm/9K0zaqWSBdSPiNYArjyaoW/G2PDLg==
dependencies:
socket.io "4.5.2"
socket.io "4.5.3"
tslib "2.4.0"

"@nestjs/schematics@^9.0.0":
Expand All @@ -759,10 +759,10 @@
dependencies:
tslib "2.4.0"

"@nestjs/websockets@^9.1.5":
version "9.1.5"
resolved "https://registry.yarnpkg.com/@nestjs/websockets/-/websockets-9.1.5.tgz#ade59681b1fe5ac4b798f7d125b6379a3bc99c33"
integrity sha512-HRSS9fERC2KcoHKGz66ObDOYwIpsCX0ZqrVrquMY+lrXCBANcSs+X7BUYtiB9mssHsXBuIZpuIKCpQeQpE7iBA==
"@nestjs/websockets@^9.1.6":
version "9.1.6"
resolved "https://registry.yarnpkg.com/@nestjs/websockets/-/websockets-9.1.6.tgz#db23702c7f9c24234b4bf194da7b0a6c1621dd69"
integrity sha512-n6ldWU2FdVFESTj0ahmGLDEOT0sc3QKLya7N/L7dh8Z5F50gqd5Qw6LPmhRWcyXLGi+1Ugn1ZMnLn62B1CsZ7A==
dependencies:
iterare "1.2.1"
object-hash "3.0.0"
Expand Down Expand Up @@ -798,7 +798,7 @@
consola "^2.15.0"
node-fetch "^2.6.1"

"@prisma/client@^4.5.0":
"@prisma/client@4.5.0":
version "4.5.0"
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.5.0.tgz#f708549bee3da396d5741d846b4e4306b120210c"
integrity sha512-B2cV0OPI1smhdYUxsJoLYQLoMlLH06MUxgFUWQnHodGMX98VRVXKmQE/9OcrTNkqtke5RC+YU24Szxd04tZA2g==
Expand Down Expand Up @@ -997,11 +997,16 @@
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==

"@types/node@*", "@types/node@>=10.0.0":
"@types/node@*":
version "18.11.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.3.tgz#78a6d7ec962b596fc2d2ec102c4dd3ef073fea6a"
integrity sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==

"@types/node@>=10.0.0":
version "18.11.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.5.tgz#1bc94cf2f9ab5fe33353bc7c79c797dcc5325bef"
integrity sha512-3JRwhbjI+cHLAkUorhf8RnqUbFXajvzX4q6fMn5JwkgtuwfYtRQYI3u4V92vI6NJuTsbBQWWh3RZjFsuevyMGQ==

"@types/node@^16.0.0":
version "16.11.68"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.68.tgz#30ee923f4d940793e0380f5ce61c0bd4b7196b6c"
Expand Down Expand Up @@ -1030,6 +1035,13 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.12.tgz#920447fdd78d76b19de0438b7f60df3c4a80bf1c"
integrity sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==

"@types/socket.io@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/socket.io/-/socket.io-3.0.2.tgz#606c9639e3f93bb8454cba8f5f0a283d47917759"
integrity sha512-pu0sN9m5VjCxBZVK8hW37ZcMe8rjn4HHggBN5CbaRTvFwv5jOmuIRZEuddsBPa9Th0ts0SIo3Niukq+95cMBbQ==
dependencies:
socket.io "*"

"@types/source-map-support@^0.5.6":
version "0.5.6"
resolved "https://registry.yarnpkg.com/@types/source-map-support/-/source-map-support-0.5.6.tgz#aa4a8c98ec73a1f1f30a813573a9b2154a6eb39a"
Expand Down Expand Up @@ -4900,19 +4912,7 @@ socket.io-parser@~4.2.0:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.1"

socket.io@4.5.2:
version "4.5.2"
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.2.tgz#1eb25fd380ab3d63470aa8279f8e48d922d443ac"
integrity sha512-6fCnk4ARMPZN448+SQcnn1u8OHUC72puJcNtSgg2xS34Cu7br1gQ09YKkO1PFfDn/wyUE9ZgMAwosJed003+NQ==
dependencies:
accepts "~1.3.4"
base64id "~2.0.0"
debug "~4.3.2"
engine.io "~6.2.0"
socket.io-adapter "~2.4.0"
socket.io-parser "~4.2.0"

socket.io@^4.5.3:
socket.io@*, socket.io@4.5.3, socket.io@^4.5.3:
version "4.5.3"
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.3.tgz#44dffea48d7f5aa41df4a66377c386b953bc521c"
integrity sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"socket.io": "^4.5.3",
"socket.io-client": "^4.5.3",
"typescript": "4.8.4",
"typesync": "^0.9.2",
"zustand": "^4.1.3"
},
"lint-staged": {
Expand Down
Loading

0 comments on commit f4bcfb5

Please sign in to comment.