Template
feat: working on messages
This commit is contained in:
+1
-1
Submodule events updated: cdddb9a073...22656ba608
Generated
+10
-7
@@ -21,7 +21,7 @@
|
|||||||
"connect-redis": "^8.0.1",
|
"connect-redis": "^8.0.1",
|
||||||
"express-session": "^1.18.0",
|
"express-session": "^1.18.0",
|
||||||
"pg": "^8.13.1",
|
"pg": "^8.13.1",
|
||||||
"ranjs": "^1.24.5",
|
"random": "^5.1.1",
|
||||||
"redis": "^4.7.0",
|
"redis": "^4.7.0",
|
||||||
"reflect-metadata": "^0.2.1",
|
"reflect-metadata": "^0.2.1",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
@@ -10074,6 +10074,15 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/random": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/random/-/random-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-iidvORUvXY1ItoYxO0eduHCKl22QV0G6460vRHe862dUagJKPhRyjUGwK8ioOCG4NRuFvExHFpqMngsnr2miwA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/random-bytes": {
|
"node_modules/random-bytes": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
|
||||||
@@ -10101,12 +10110,6 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ranjs": {
|
|
||||||
"version": "1.24.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/ranjs/-/ranjs-1.24.5.tgz",
|
|
||||||
"integrity": "sha512-ZW4Bgc5jPRDYqBWuTcwS3GgSMemG5t+eltzS1aGIM7AVBx3JJymqqWN+TiKb5t0gfK//lsJUYPDkNsZ+oLIXIQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/raw-body": {
|
"node_modules/raw-body": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@
|
|||||||
"connect-redis": "^8.0.1",
|
"connect-redis": "^8.0.1",
|
||||||
"express-session": "^1.18.0",
|
"express-session": "^1.18.0",
|
||||||
"pg": "^8.13.1",
|
"pg": "^8.13.1",
|
||||||
"ranjs": "^1.24.5",
|
"random": "^5.1.1",
|
||||||
"redis": "^4.7.0",
|
"redis": "^4.7.0",
|
||||||
"reflect-metadata": "^0.2.1",
|
"reflect-metadata": "^0.2.1",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
|
|||||||
+11
-1
@@ -13,6 +13,7 @@ import { Concept } from './games/entities/concept.entity';
|
|||||||
import { ConceptInTurn } from './games/entities/concept_in_turn.entity';
|
import { ConceptInTurn } from './games/entities/concept_in_turn.entity';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { WordModule } from './word/words.module';
|
import { WordModule } from './word/words.module';
|
||||||
|
import { Message } from './games/entities/message.entity';
|
||||||
|
|
||||||
const configService = new ConfigService();
|
const configService = new ConfigService();
|
||||||
|
|
||||||
@@ -31,7 +32,16 @@ const configService = new ConfigService();
|
|||||||
username: configService.get('PG_USER'),
|
username: configService.get('PG_USER'),
|
||||||
database: 'concept',
|
database: 'concept',
|
||||||
synchronize: configService.get('DEV_MODE') == 'true',
|
synchronize: configService.get('DEV_MODE') == 'true',
|
||||||
entities: [User, Player, Game, Concept, ConceptInTurn, Topic, Word],
|
entities: [
|
||||||
|
User,
|
||||||
|
Player,
|
||||||
|
Game,
|
||||||
|
Message,
|
||||||
|
Concept,
|
||||||
|
ConceptInTurn,
|
||||||
|
Topic,
|
||||||
|
Word,
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
GamesModule,
|
GamesModule,
|
||||||
UsersModule,
|
UsersModule,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
|
Get,
|
||||||
HttpException,
|
HttpException,
|
||||||
HttpStatus,
|
HttpStatus,
|
||||||
Param,
|
Param,
|
||||||
@@ -11,7 +12,7 @@ import {
|
|||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { LobbyService } from '../services/lobby.service';
|
import { LobbyService } from '../services/lobby.service';
|
||||||
import { AuthGuard } from '../../users/guards/auth.guard';
|
import { AuthGuard } from '../../users/guards/auth.guard';
|
||||||
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
import { ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||||
import { Game } from '../entities/game.entity';
|
import { Game } from '../entities/game.entity';
|
||||||
import { GamePipe, GameStartedPipe } from '../pipe/game.pipe';
|
import { GamePipe, GameStartedPipe } from '../pipe/game.pipe';
|
||||||
|
|
||||||
@@ -20,6 +21,8 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
|
|||||||
import { GameService } from '../services/games.service';
|
import { GameService } from '../services/games.service';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { SessionData } from 'express-session';
|
import { SessionData } from 'express-session';
|
||||||
|
import { WordResponseDTO } from 'events/dto/wordresponse.dto';
|
||||||
|
import { WordRecieveDTO } from 'src/word/dto/wordrecieve.dto';
|
||||||
|
|
||||||
@ApiTags('game')
|
@ApiTags('game')
|
||||||
@Controller('games/:id')
|
@Controller('games/:id')
|
||||||
@@ -60,7 +63,7 @@ export class GamesController {
|
|||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (game.owner.id != session.user.id) {
|
if (game.ownerId != session.user?.id) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
'You can only start games you own',
|
'You can only start games you own',
|
||||||
HttpStatus.FORBIDDEN,
|
HttpStatus.FORBIDDEN,
|
||||||
@@ -88,12 +91,12 @@ export class GamesController {
|
|||||||
@ApiOperation({ summary: 'Kick a player' })
|
@ApiOperation({ summary: 'Kick a player' })
|
||||||
@UseGuards(AuthGuard)
|
@UseGuards(AuthGuard)
|
||||||
kick(
|
kick(
|
||||||
@Param('id') id: string,
|
|
||||||
@Session() session: SessionData,
|
@Session() session: SessionData,
|
||||||
|
@Param('id') id: string,
|
||||||
@Param('id', GamePipe) game: Game,
|
@Param('id', GamePipe) game: Game,
|
||||||
@Param('playerId') playerId: string,
|
@Param('playerId') playerId: string,
|
||||||
) {
|
) {
|
||||||
if (session.user.id != game.owner.id) {
|
if (session.user.id != game.ownerId) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
'You do do not own this game',
|
'You do do not own this game',
|
||||||
HttpStatus.FORBIDDEN,
|
HttpStatus.FORBIDDEN,
|
||||||
@@ -102,6 +105,43 @@ export class GamesController {
|
|||||||
return this.lobbyService.kickPlayer(game, session.user, playerId);
|
return this.lobbyService.kickPlayer(game, session.user, playerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('currentWord')
|
||||||
|
@ApiOperation({ summary: 'Read Current Word' })
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
getCurrentWord(
|
||||||
|
@Session() session: SessionData,
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Param('id', GamePipe) game: Game,
|
||||||
|
) {
|
||||||
|
if (session.user.id != game.currentPlayer.userId) {
|
||||||
|
throw new HttpException(
|
||||||
|
'It is not your turn to play',
|
||||||
|
HttpStatus.FORBIDDEN,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new WordResponseDTO(game.currentWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/message')
|
||||||
|
@ApiOperation({ summary: 'try to guess a word' })
|
||||||
|
@ApiBody({ type: WordRecieveDTO })
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
async postMessage(
|
||||||
|
@Session() session: SessionData,
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Param('id', GamePipe) game: Game,
|
||||||
|
@Body('value') value: string,
|
||||||
|
) {
|
||||||
|
const player = game.players.find((p) => p.userId == session.user.id);
|
||||||
|
if (!game.started) {
|
||||||
|
throw new HttpException('Game not started', HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
if (!player) {
|
||||||
|
throw new HttpException('You are not in this game', HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
await this.gameService.postMessage(game, player, value);
|
||||||
|
}
|
||||||
|
|
||||||
@Sse('/subscribe')
|
@Sse('/subscribe')
|
||||||
subscribe(@Param('id') id: string): Observable<{ data: string }> {
|
subscribe(@Param('id') id: string): Observable<{ data: string }> {
|
||||||
return fromEvent(this.eventEmitter, 'sse.game.' + id).pipe(
|
return fromEvent(this.eventEmitter, 'sse.game.' + id).pipe(
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export class LobbyController {
|
|||||||
@Param('id', GamePipe) game: Game,
|
@Param('id', GamePipe) game: Game,
|
||||||
@GetUser() user: User,
|
@GetUser() user: User,
|
||||||
) {
|
) {
|
||||||
if (game.owner.id != user.id) {
|
if (game.ownerId != user.id) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
'You can only delete games you own',
|
'You can only delete games you own',
|
||||||
HttpStatus.FORBIDDEN,
|
HttpStatus.FORBIDDEN,
|
||||||
@@ -110,7 +110,7 @@ export class LobbyController {
|
|||||||
throw new HttpException('Game already started', HttpStatus.BAD_REQUEST);
|
throw new HttpException('Game already started', HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game.players.some((p) => p.user.id == user.id)) {
|
if (game.players.some((p) => p.userId == user.id)) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
'You are already in this game',
|
'You are already in this game',
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export class MessageRecieveDTO {
|
||||||
|
constructor(partial: Partial<MessageRecieveDTO>) {
|
||||||
|
this.value = partial.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
Column,
|
Column,
|
||||||
Entity,
|
Entity,
|
||||||
|
JoinColumn,
|
||||||
JoinTable,
|
JoinTable,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
OneToMany,
|
OneToMany,
|
||||||
@@ -10,6 +11,8 @@ import {
|
|||||||
import { Player } from './player.entity';
|
import { Player } from './player.entity';
|
||||||
import { ConceptInTurn } from './concept_in_turn.entity';
|
import { ConceptInTurn } from './concept_in_turn.entity';
|
||||||
import { User } from 'src/users/entities/user.entity';
|
import { User } from 'src/users/entities/user.entity';
|
||||||
|
import { Word } from 'src/word/entities/word.entity';
|
||||||
|
import { Message } from './message.entity';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Game {
|
export class Game {
|
||||||
@@ -19,8 +22,12 @@ export class Game {
|
|||||||
@Column()
|
@Column()
|
||||||
seed: string;
|
seed: string;
|
||||||
|
|
||||||
@ManyToOne(() => User, { eager: true })
|
@JoinColumn({ name: 'ownerId' })
|
||||||
owner: User;
|
@ManyToOne(() => User)
|
||||||
|
owner: Promise<User>;
|
||||||
|
|
||||||
|
@Column({ name: 'ownerId' })
|
||||||
|
ownerId: string;
|
||||||
|
|
||||||
@OneToMany(() => Player, (player) => player.game, {
|
@OneToMany(() => Player, (player) => player.game, {
|
||||||
eager: true,
|
eager: true,
|
||||||
@@ -28,15 +35,32 @@ export class Game {
|
|||||||
@JoinTable()
|
@JoinTable()
|
||||||
players: Player[];
|
players: Player[];
|
||||||
|
|
||||||
@OneToOne(() => Player)
|
@OneToOne(() => Player, { nullable: true, eager: true })
|
||||||
|
@JoinColumn()
|
||||||
currentPlayer: Player;
|
currentPlayer: Player;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@ManyToOne(() => Word, { nullable: true, eager: true })
|
||||||
currentWord: string;
|
currentWord: Word;
|
||||||
|
|
||||||
@Column({ default: false })
|
@Column({ default: false })
|
||||||
started: boolean;
|
started: boolean;
|
||||||
|
|
||||||
@OneToMany(() => ConceptInTurn, (cit) => cit.game, { onDelete: 'CASCADE' })
|
@Column({ default: 0 })
|
||||||
|
turn: number = 0;
|
||||||
|
|
||||||
|
@OneToMany(() => ConceptInTurn, (cit) => cit.game, {
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
eager: true,
|
||||||
|
})
|
||||||
currentConcepts: ConceptInTurn[];
|
currentConcepts: ConceptInTurn[];
|
||||||
|
|
||||||
|
@OneToMany(() => Message, (msg) => msg.game, {
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
eager: true,
|
||||||
|
})
|
||||||
|
_messages: Message[];
|
||||||
|
|
||||||
|
get messages() {
|
||||||
|
return this._messages.sort((a, b) => a.id - b.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
JoinColumn,
|
||||||
|
ManyToOne,
|
||||||
|
OneToMany,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Unique,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { Player } from './player.entity';
|
||||||
|
|
||||||
|
import { Game } from './game.entity';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class Message {
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
@JoinColumn({ name: 'authorId' })
|
||||||
|
@ManyToOne(() => Player, { eager: true })
|
||||||
|
author: Player;
|
||||||
|
|
||||||
|
get authorId() {
|
||||||
|
return this.author.userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManyToOne(() => Game)
|
||||||
|
game: Promise<Game>;
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { User } from '../../users/entities/user.entity';
|
|||||||
import {
|
import {
|
||||||
Column,
|
Column,
|
||||||
Entity,
|
Entity,
|
||||||
|
JoinColumn,
|
||||||
JoinTable,
|
JoinTable,
|
||||||
ManyToMany,
|
ManyToMany,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
@@ -16,8 +17,12 @@ export class Player {
|
|||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
@ManyToOne(() => User, { eager: true, onDelete: 'CASCADE' })
|
@JoinColumn({ name: 'userId' })
|
||||||
user: User;
|
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
||||||
|
user: Promise<User>;
|
||||||
|
|
||||||
|
@Column({ name: 'userId' })
|
||||||
|
userId: string;
|
||||||
|
|
||||||
@ManyToOne(() => Game, { onDelete: 'CASCADE' })
|
@ManyToOne(() => Game, { onDelete: 'CASCADE' })
|
||||||
game: Game;
|
game: Game;
|
||||||
|
|||||||
@@ -8,13 +8,16 @@ import { GameService } from './services/games.service';
|
|||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { Player } from './entities/player.entity';
|
import { Player } from './entities/player.entity';
|
||||||
import { User } from 'src/users/entities/user.entity';
|
import { User } from 'src/users/entities/user.entity';
|
||||||
|
import { WordModule } from 'src/word/words.module';
|
||||||
|
import { Message } from './entities/message.entity';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
UsersModule,
|
UsersModule,
|
||||||
|
WordModule,
|
||||||
TypeOrmModule.forFeature([Game]),
|
TypeOrmModule.forFeature([Game]),
|
||||||
TypeOrmModule.forFeature([Player]),
|
TypeOrmModule.forFeature([Player]),
|
||||||
TypeOrmModule.forFeature([User]),
|
TypeOrmModule.forFeature([Message]),
|
||||||
],
|
],
|
||||||
controllers: [LobbyController, GamesController],
|
controllers: [LobbyController, GamesController],
|
||||||
providers: [LobbyService, GameService],
|
providers: [LobbyService, GameService],
|
||||||
|
|||||||
@@ -12,15 +12,58 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
|
|||||||
import { Player } from '../entities/player.entity';
|
import { Player } from '../entities/player.entity';
|
||||||
import { User } from 'src/users/entities/user.entity';
|
import { User } from 'src/users/entities/user.entity';
|
||||||
|
|
||||||
|
import { WordService } from 'src/word/services/word.service';
|
||||||
|
import {
|
||||||
|
GameMessageDeleteEvent,
|
||||||
|
GameMessageEvent,
|
||||||
|
GameStartEvent,
|
||||||
|
} from 'events/game.events';
|
||||||
|
import random from 'random';
|
||||||
|
import { platform } from 'os';
|
||||||
|
import { Message } from '../entities/message.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GameService {
|
export class GameService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Game) private gameRepository: Repository<Game>,
|
@InjectRepository(Game) private gameRepository: Repository<Game>,
|
||||||
|
@InjectRepository(Message) private messageResporitory: Repository<Message>,
|
||||||
|
private readonly wordService: WordService,
|
||||||
private eventEmitter: EventEmitter2,
|
private eventEmitter: EventEmitter2,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async start(game: Game) {
|
async start(game: Game) {
|
||||||
throw Error('Not Implemented');
|
const rng = random.clone(game.seed);
|
||||||
|
game.started = true;
|
||||||
|
game.currentPlayer = rng.choice(game.players);
|
||||||
|
const words = await this.wordService.listActive();
|
||||||
|
game.currentWord = rng.choice(words);
|
||||||
|
|
||||||
|
await this.gameRepository.save(game);
|
||||||
|
this.eventEmitter.emit(
|
||||||
|
'sse.game.' + game.id,
|
||||||
|
new GameStartEvent(game.currentPlayer),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async postMessage(game: Game, author: Player, value: string) {
|
||||||
|
const message = this.messageResporitory.create();
|
||||||
|
message.author = author;
|
||||||
|
message.game = Promise.resolve(game);
|
||||||
|
message.value = value;
|
||||||
|
await this.messageResporitory.save(message);
|
||||||
|
this.eventEmitter.emit(
|
||||||
|
'sse.game.' + game.id,
|
||||||
|
new GameMessageEvent(message),
|
||||||
|
);
|
||||||
|
const oldMessage = game.messages[0];
|
||||||
|
const oldMessageId = oldMessage.id;
|
||||||
|
if (game.messages.length > 3) {
|
||||||
|
await this.messageResporitory.remove(oldMessage);
|
||||||
|
}
|
||||||
|
this.eventEmitter.emit(
|
||||||
|
'sse.game.' + game.id,
|
||||||
|
new GameMessageDeleteEvent(oldMessageId),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async end(game: Game, winner: Player) {
|
async end(game: Game, winner: Player) {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export class LobbyService {
|
|||||||
|
|
||||||
async create(owner: User) {
|
async create(owner: User) {
|
||||||
const createdGame = this.gameRepository.create();
|
const createdGame = this.gameRepository.create();
|
||||||
createdGame.owner = owner;
|
createdGame.owner = Promise.resolve(owner);
|
||||||
createdGame.seed = randomUUID();
|
createdGame.seed = randomUUID();
|
||||||
|
|
||||||
await this.gameRepository.save(createdGame);
|
await this.gameRepository.save(createdGame);
|
||||||
@@ -40,11 +40,11 @@ export class LobbyService {
|
|||||||
|
|
||||||
async joinGame(game: Game, user: User) {
|
async joinGame(game: Game, user: User) {
|
||||||
const player = this.playerRepository.create();
|
const player = this.playerRepository.create();
|
||||||
player.user = user;
|
player.user = Promise.resolve(user);
|
||||||
player.game = game;
|
player.game = game;
|
||||||
|
await this.playerRepository.save(player);
|
||||||
this.eventEmitter.emit('sse.lobby', new LobbyJoinEvent(player, game));
|
this.eventEmitter.emit('sse.lobby', new LobbyJoinEvent(player, game));
|
||||||
this.eventEmitter.emit('sse.game.' + game.id, new GameJoinEvent(player));
|
this.eventEmitter.emit('sse.game.' + game.id, new GameJoinEvent(player));
|
||||||
await this.playerRepository.save(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
findByOwner(user: User) {
|
findByOwner(user: User) {
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ export class Topic {
|
|||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@ManyToMany((type) => Word, (word) => word.topics)
|
@ManyToMany((type) => Word, (word) => word.topics)
|
||||||
words: Word[];
|
words: Promise<Word[]>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class Word {
|
|||||||
|
|
||||||
@JoinColumn({ name: 'ownerId' })
|
@JoinColumn({ name: 'ownerId' })
|
||||||
@ManyToOne(() => User)
|
@ManyToOne(() => User)
|
||||||
owner: User;
|
owner: Promise<User>;
|
||||||
|
|
||||||
@Column({ name: 'ownerId' })
|
@Column({ name: 'ownerId' })
|
||||||
ownerId: string;
|
ownerId: string;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export class WordService {
|
|||||||
|
|
||||||
async create(value: string, owner: User) {
|
async create(value: string, owner: User) {
|
||||||
const word = this.wordRepository.create();
|
const word = this.wordRepository.create();
|
||||||
word.owner = owner;
|
word.owner = Promise.resolve(owner);
|
||||||
word.value = value;
|
word.value = value;
|
||||||
try {
|
try {
|
||||||
await this.wordRepository.save(word);
|
await this.wordRepository.save(word);
|
||||||
|
|||||||
@@ -10,5 +10,6 @@ import { UsersModule } from 'src/users/users.module';
|
|||||||
imports: [UsersModule, TypeOrmModule.forFeature([Word])],
|
imports: [UsersModule, TypeOrmModule.forFeature([Word])],
|
||||||
controllers: [WordController],
|
controllers: [WordController],
|
||||||
providers: [WordService],
|
providers: [WordService],
|
||||||
|
exports: [WordService],
|
||||||
})
|
})
|
||||||
export class WordModule {}
|
export class WordModule {}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { User } from '../users/entities/user.entity';
|
import { type User } from 'src/users/entities/user.entity';
|
||||||
declare module 'express-session' {
|
declare module 'express-session' {
|
||||||
interface SessionData {
|
interface SessionData {
|
||||||
user?: User;
|
user?: User;
|
||||||
|
|||||||
Reference in New Issue
Block a user