@builder6/rooms 0.9.3 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +1 -0
  2. package/dist/rooms/app.controller.d.ts +10 -0
  3. package/dist/rooms/app.controller.js +73 -0
  4. package/dist/rooms/app.controller.js.map +1 -0
  5. package/dist/rooms/dtos/notifications.dto.d.ts +10 -0
  6. package/dist/rooms/dtos/notifications.dto.js +7 -0
  7. package/dist/rooms/dtos/notifications.dto.js.map +1 -0
  8. package/dist/rooms/dtos/room_members.dto.d.ts +7 -0
  9. package/dist/rooms/dtos/room_members.dto.js +52 -0
  10. package/dist/rooms/dtos/room_members.dto.js.map +1 -0
  11. package/dist/rooms/dtos/rooms.dto.d.ts +12 -0
  12. package/dist/rooms/dtos/rooms.dto.js +59 -0
  13. package/dist/rooms/dtos/rooms.dto.js.map +1 -0
  14. package/dist/rooms/notifications.service.d.ts +18 -0
  15. package/dist/rooms/notifications.service.js +66 -0
  16. package/dist/rooms/notifications.service.js.map +1 -0
  17. package/dist/rooms/rooms.controller.d.ts +31 -6
  18. package/dist/rooms/rooms.controller.js +119 -24
  19. package/dist/rooms/rooms.controller.js.map +1 -1
  20. package/dist/rooms/rooms.gateway.d.ts +3 -1
  21. package/dist/rooms/rooms.gateway.js +12 -5
  22. package/dist/rooms/rooms.gateway.js.map +1 -1
  23. package/dist/rooms/rooms.guard.d.ts +1 -3
  24. package/dist/rooms/rooms.guard.js +2 -5
  25. package/dist/rooms/rooms.guard.js.map +1 -1
  26. package/dist/rooms/rooms.module.js +7 -2
  27. package/dist/rooms/rooms.module.js.map +1 -1
  28. package/dist/rooms/rooms.moleculer.d.ts +11 -0
  29. package/dist/rooms/rooms.moleculer.js +91 -0
  30. package/dist/rooms/rooms.moleculer.js.map +1 -0
  31. package/dist/rooms/rooms.service.d.ts +35 -4
  32. package/dist/rooms/rooms.service.js +146 -8
  33. package/dist/rooms/rooms.service.js.map +1 -1
  34. package/package.json +12 -3
  35. package/src/rooms/app.controller.ts +63 -0
  36. package/src/rooms/dtos/notifications.dto.ts +10 -0
  37. package/src/rooms/dtos/room_members.dto.ts +29 -0
  38. package/src/rooms/dtos/rooms.dto.ts +51 -0
  39. package/src/rooms/notifications.service.ts +82 -0
  40. package/src/rooms/rooms.controller.ts +132 -16
  41. package/src/rooms/rooms.gateway.ts +17 -4
  42. package/src/rooms/rooms.guard.ts +1 -1
  43. package/src/rooms/rooms.module.ts +7 -2
  44. package/src/rooms/rooms.moleculer.ts +78 -0
  45. package/src/rooms/rooms.service.ts +210 -6
  46. package/.eslintrc.js +0 -25
@@ -1,5 +1,6 @@
1
- import { AuthGuard } from '@builder6/core';
1
+ import { AuthGuard, FilesService } from '@builder6/core';
2
2
  import { RoomsService } from './rooms.service';
3
+ import { omit, uniqBy } from 'lodash';
3
4
  import {
4
5
  Controller,
5
6
  Get,
@@ -18,9 +19,10 @@ import { JwtService } from '@nestjs/jwt';
18
19
  import { RoomsGuard } from './rooms.guard';
19
20
  import * as rawBody from 'raw-body';
20
21
  import { Request } from 'express';
21
- import { FilesService } from '@builder6/core';
22
22
  import { RoomsGateway } from './rooms.gateway';
23
23
  import { ServerMsgCode } from './protocol/ServerMsg';
24
+ import { READ_ACCESS } from './dtos/rooms.dto';
25
+ import { NotificationsService } from './notifications.service';
24
26
 
25
27
  @Controller('v2/c/')
26
28
  export class RoomsController {
@@ -29,6 +31,7 @@ export class RoomsController {
29
31
  private filesService: FilesService,
30
32
  private jwtService: JwtService,
31
33
  private roomsGateway: RoomsGateway,
34
+ private notificationsService: NotificationsService,
32
35
  ) {}
33
36
 
34
37
  @UseGuards(AuthGuard)
@@ -38,18 +41,12 @@ export class RoomsController {
38
41
  @Req() req: Request,
39
42
  ) {
40
43
  const user = req['user'];
41
- const { room = 'undefined', permission = 'read' } = body;
42
- let perm = ['room:read'];
43
- if (permission === 'write') {
44
- perm = ['room:write'];
45
- }
46
- const perms = {
47
- [room]: perm,
48
- };
49
- return await this.roomsService.getToken({
44
+ const { room = 'test', permission = 'read' } = body;
45
+ return await this.roomsService.getRoomToken({
50
46
  spaceId: user.space,
51
47
  userId: user.user,
52
- perms: perms,
48
+ roomId: room,
49
+ readonly: permission === 'read',
53
50
  });
54
51
  }
55
52
 
@@ -78,11 +75,18 @@ export class RoomsController {
78
75
 
79
76
  @UseGuards(RoomsGuard)
80
77
  @Get('rooms/:roomId/threads')
81
- async getThreads(@Param('roomId') roomId: string) {
78
+ async getThreads(@Req() req: Request, @Param('roomId') roomId: string) {
82
79
  const threads = await this.roomsService.getThreads(roomId);
80
+ const inboxNotifications =
81
+ await this.notificationsService.findNotifications({
82
+ userId: req['jwt'].uid,
83
+ roomId,
84
+ });
83
85
  return {
84
86
  data: threads,
85
- inboxNotifications: [],
87
+ inboxNotifications: inboxNotifications.map((inboxNotification) =>
88
+ omit(inboxNotification, ['userId', '_id']),
89
+ ),
86
90
  meta: {
87
91
  nextCursor: null,
88
92
  requestedAt: new Date().toISOString() as string,
@@ -98,14 +102,23 @@ export class RoomsController {
98
102
  @UseGuards(RoomsGuard)
99
103
  @Get('rooms/:roomId/threads/delta')
100
104
  async getThreadsDelta(
105
+ @Req() req: Request,
101
106
  @Param('roomId') roomId: string,
102
107
  @Query('since') since: string,
103
108
  ) {
104
109
  const sinceDate = new Date(since);
105
110
  const threads = await this.roomsService.getThreads(roomId, sinceDate);
111
+ const inboxNotifications =
112
+ await this.notificationsService.findNotifications({
113
+ userId: req['jwt'].uid,
114
+ roomId,
115
+ sinceDate,
116
+ });
106
117
  return {
107
118
  data: threads,
108
- inboxNotifications: [],
119
+ inboxNotifications: inboxNotifications.map((inboxNotification) =>
120
+ omit(inboxNotification, ['userId', '_id']),
121
+ ),
109
122
  meta: {
110
123
  nextCursor: null,
111
124
  requestedAt: new Date().toISOString() as string,
@@ -156,7 +169,18 @@ export class RoomsController {
156
169
  @Param('threadId') threadId: string,
157
170
  ) {
158
171
  const thread = await this.roomsService.getThread(roomId, threadId);
159
- return { thread };
172
+ const inboxNotifications =
173
+ await this.notificationsService.findNotifications({
174
+ userId: req['jwt'].uid,
175
+ roomId,
176
+ threadId,
177
+ });
178
+ return {
179
+ thread,
180
+ inboxNotification: inboxNotifications[0]
181
+ ? omit(inboxNotifications[0], ['userId', '_id'])
182
+ : undefined,
183
+ };
160
184
  }
161
185
 
162
186
  @UseGuards(RoomsGuard)
@@ -269,7 +293,98 @@ export class RoomsController {
269
293
  return {};
270
294
  }
271
295
 
296
+ // 获取通知
297
+ @UseGuards(RoomsGuard)
298
+ @Get('inbox-notifications')
299
+ async getInboxNotifications(
300
+ @Req() req: Request,
301
+ @Query('unread') unread: string,
302
+ @Query('limit') limit: string,
303
+ ) {
304
+ const userId = req['jwt'].uid;
305
+ const requestedAt = new Date();
306
+ const notifications = await this.notificationsService.findNotifications({
307
+ userId,
308
+ unread: unread === 'true',
309
+ limit: Number(limit),
310
+ });
311
+ const threads = await this.roomsService.getThreadsByIds(
312
+ uniqBy(
313
+ notifications,
314
+ (notification) => `${notification.roomId}-${notification.threadId}`,
315
+ ),
316
+ );
317
+ return {
318
+ inboxNotifications: notifications.map((notification) =>
319
+ omit(notification, ['userId', '_id']),
320
+ ),
321
+ threads,
322
+ meta: {
323
+ nextCursor: null,
324
+ requestedAt,
325
+ },
326
+ deletedThreads: [],
327
+ deletedInboxNotifications: [],
328
+ };
329
+ }
330
+
331
+ // 获取增量通知
332
+ @UseGuards(RoomsGuard)
333
+ @Get('inbox-notifications/delta')
334
+ async getInboxNotificationsSince(
335
+ @Req() req: Request,
336
+ @Query('since') since: string,
337
+ ) {
338
+ const userId = req['jwt'].uid;
339
+ const sinceDate = new Date(since);
340
+ const requestedAt = new Date();
341
+ const notifications = await this.notificationsService.findNotifications({
342
+ userId,
343
+ sinceDate,
344
+ });
345
+ const threads = await this.roomsService.getThreadsByIds(
346
+ uniqBy(
347
+ notifications,
348
+ (notification) => `${notification.roomId}-${notification.threadId}`,
349
+ ),
350
+ );
351
+ return {
352
+ inboxNotifications: notifications.map((notification) =>
353
+ omit(notification, ['userId', '_id']),
354
+ ),
355
+ threads,
356
+ meta: { requestedAt },
357
+ deletedThreads: [],
358
+ deletedInboxNotifications: [],
359
+ };
360
+ }
361
+
362
+ // read
363
+ @UseGuards(RoomsGuard)
364
+ @Post('rooms/:roomId/inbox-notifications/read')
365
+ async read(
366
+ @Req() req: Request,
367
+ @Param('roomId') roomId: string,
368
+ @Body('inboxNotificationIds') inboxNotificationIds: string[],
369
+ ) {
370
+ const userId = req['jwt'].uid;
371
+ const notifications = await this.notificationsService.markAsRead(
372
+ roomId,
373
+ userId,
374
+ inboxNotificationIds,
375
+ );
376
+ return {
377
+ data:
378
+ notifications?.length > 0
379
+ ? notifications.map((notification) =>
380
+ omit(notification, ['userId', '_id']),
381
+ )
382
+ : undefined,
383
+ };
384
+ }
385
+
272
386
  // 获取下载Url
387
+ @UseGuards(RoomsGuard)
273
388
  @Post('rooms/:roomId/attachments/presigned-urls')
274
389
  async presignedUrls(@Body('attachmentIds') attachmentIds: string[]) {
275
390
  const urls = await Promise.all(
@@ -284,6 +399,7 @@ export class RoomsController {
284
399
  }
285
400
 
286
401
  // 上传文件
402
+ @UseGuards(RoomsGuard)
287
403
  @Put('rooms/:roomId/attachments/:attachmentId/upload/:fileName')
288
404
  async uploadFile(
289
405
  @Param('roomId') roomId: string,
@@ -11,6 +11,7 @@ import * as url from 'url';
11
11
  import { v4 as uuidv4 } from 'uuid';
12
12
  import { ServerMsgCode, ServerMsg } from './protocol/ServerMsg';
13
13
  import { JwtService } from '@nestjs/jwt';
14
+ import { RoomsService } from './rooms.service';
14
15
 
15
16
  interface RoomState {
16
17
  roomId: string;
@@ -37,7 +38,10 @@ export class RoomsGateway implements OnGatewayConnection {
37
38
  private redis: Redis;
38
39
  private pubRedis: Redis;
39
40
 
40
- constructor(private jwtService: JwtService) {
41
+ constructor(
42
+ private jwtService: JwtService,
43
+ private roomsService: RoomsService,
44
+ ) {
41
45
  this.redis = new Redis('redis://localhost:6379');
42
46
  this.pubRedis = new Redis('redis://localhost:6379');
43
47
  }
@@ -113,6 +117,12 @@ export class RoomsGateway implements OnGatewayConnection {
113
117
  payload: { roomId: string; userId: string },
114
118
  ) {
115
119
  const { roomId, userId } = payload;
120
+
121
+ const room = await this.roomsService.getRoom(roomId);
122
+ if (!room) {
123
+ throw new Error('Room not found');
124
+ }
125
+
116
126
  let roomState = this.roomStates.get(roomId);
117
127
 
118
128
  if (!roomState) {
@@ -142,11 +152,14 @@ export class RoomsGateway implements OnGatewayConnection {
142
152
  Object.keys(roomState.connections).map(async (connId) => {
143
153
  const connection = roomState.connections[parseInt(connId)];
144
154
  const roomId = connection.roomId;
145
- const scopes = await this.getUserScopes(roomId, connection.userId);
155
+ const member = await this.roomsService.getRoomMember(
156
+ roomId,
157
+ connection.userId,
158
+ );
146
159
  return {
147
160
  connectionId: parseInt(connId),
148
161
  userId: connection.userId,
149
- scopes,
162
+ scopes: member.scopes,
150
163
  };
151
164
  }),
152
165
  );
@@ -155,7 +168,7 @@ export class RoomsGateway implements OnGatewayConnection {
155
168
  type: ServerMsgCode.ROOM_STATE, // 使用 ServerMsgCode 枚举
156
169
  actor: connectionId,
157
170
  nonce: nonce,
158
- scopes: await this.getUserScopes(roomId, userId),
171
+ scopes: room.defaultScopes,
159
172
  users: users.reduce(
160
173
  (acc, user) => {
161
174
  acc[user.connectionId] = {
@@ -10,7 +10,7 @@ import { JwtService } from '@nestjs/jwt';
10
10
  @Injectable()
11
11
  export class RoomsGuard implements CanActivate {
12
12
  constructor(
13
- private roomsService: RoomsService,
13
+ // private roomsService: RoomsService,
14
14
  private jwtService: JwtService,
15
15
  ) {}
16
16
 
@@ -6,6 +6,10 @@ import { JwtModule } from '@nestjs/jwt';
6
6
  import { AuthModule } from '@builder6/core';
7
7
  import { RoomsGateway } from './rooms.gateway';
8
8
  import { FilesModule } from '@builder6/core';
9
+ import { PagesModule } from '@builder6/pages';
10
+ import { NotificationsService } from './notifications.service';
11
+ import { RoomsAppController } from './app.controller';
12
+ import { RoomsMoleculer } from './rooms.moleculer';
9
13
 
10
14
  /* 按照 liveblocks.io 规范实现的API */
11
15
  @Module({
@@ -13,12 +17,13 @@ import { FilesModule } from '@builder6/core';
13
17
  AuthModule,
14
18
  MongodbModule,
15
19
  FilesModule,
20
+ PagesModule,
16
21
  JwtModule.register({
17
22
  secret: process.env.B6_JWT_SECRET || 'secret',
18
23
  signOptions: { expiresIn: '60s' },
19
24
  }),
20
25
  ],
21
- controllers: [RoomsController],
22
- providers: [RoomsService, RoomsGateway],
26
+ controllers: [RoomsAppController, RoomsController],
27
+ providers: [RoomsService, RoomsGateway, NotificationsService, RoomsMoleculer],
23
28
  })
24
29
  export class RoomsModule {}
@@ -0,0 +1,78 @@
1
+ import { Service, Context, ServiceBroker } from 'moleculer';
2
+ import { Injectable } from '@nestjs/common';
3
+ import { InjectBroker } from '@builder6/moleculer';
4
+ import { RoomsService } from './rooms.service';
5
+
6
+ @Injectable()
7
+ export class RoomsMoleculer extends Service {
8
+ constructor(
9
+ private readonly roomsService: RoomsService,
10
+ @InjectBroker() broker: ServiceBroker,
11
+ ) {
12
+ super(broker);
13
+
14
+ this.parseServiceSchema({
15
+ name: '@builder6/rooms',
16
+ settings: {},
17
+ actions: {
18
+ createComment: this.createComment,
19
+ createThread: this.createThread,
20
+ },
21
+ created: this.serviceCreated,
22
+ started: this.serviceStarted,
23
+ stopped: this.serviceStopped,
24
+ });
25
+ }
26
+
27
+ serviceCreated() {}
28
+
29
+ async serviceStarted() {}
30
+
31
+ async serviceStopped() {}
32
+
33
+ async createThread(ctx: Context) {
34
+ const { id, comment, metadata, resolved, roomId, userId } =
35
+ ctx.params as any;
36
+ try {
37
+ const result = this.roomsService.createThread({
38
+ id,
39
+ comment,
40
+ metadata,
41
+ resolved,
42
+ roomId,
43
+ userId,
44
+ });
45
+ return result;
46
+ } catch (error) {
47
+ console.error(error);
48
+ return {
49
+ error: {
50
+ message: error.message,
51
+ },
52
+ };
53
+ }
54
+ }
55
+
56
+ async createComment(ctx: Context) {
57
+ const { id, attachmentIds, body, roomId, threadId, userId } =
58
+ ctx.params as any;
59
+ try {
60
+ const result = this.roomsService.createComment({
61
+ id,
62
+ attachmentIds,
63
+ body,
64
+ roomId,
65
+ threadId,
66
+ userId,
67
+ });
68
+ return result;
69
+ } catch (error) {
70
+ console.error(error);
71
+ return {
72
+ error: {
73
+ message: error.message,
74
+ },
75
+ };
76
+ }
77
+ }
78
+ }
@@ -1,6 +1,12 @@
1
1
  import { MongodbService } from '@builder6/core';
2
2
  import { JwtService } from '@nestjs/jwt';
3
3
  import { Injectable } from '@nestjs/common';
4
+ import { READ_ACCESS, RoomDTO } from './dtos/rooms.dto';
5
+ import { RoomMemberDTO } from './dtos/room_members.dto';
6
+ import { uniq } from 'lodash';
7
+ import { NotificationsService } from './notifications.service';
8
+ import { v4 as uuidv4 } from 'uuid';
9
+ import { CommentBody, CommentBodyMention } from './protocol/Comments';
4
10
 
5
11
  export interface CreateThreadParams {
6
12
  id?: string;
@@ -28,17 +34,23 @@ export interface Attachment {
28
34
  type: string;
29
35
  }
30
36
 
37
+ export enum CommentType {
38
+ Paragraph = 'paragraph',
39
+ }
40
+
41
+ export enum CommentBodyInlineType {
42
+ Mention = 'mention',
43
+ Link = 'link',
44
+ }
45
+
31
46
  @Injectable()
32
47
  export class RoomsService {
33
48
  constructor(
34
49
  private mongodbService: MongodbService,
35
50
  private jwtService: JwtService,
51
+ private notificationsService: NotificationsService,
36
52
  ) {}
37
53
 
38
- async getRoom(roomId: string) {
39
- return { _id: roomId };
40
- }
41
-
42
54
  async getToken({
43
55
  spaceId,
44
56
  userId,
@@ -54,14 +66,52 @@ export class RoomsService {
54
66
  sid: spaceId,
55
67
  uid: userId,
56
68
  mcpr: 10,
57
- perms: {},
69
+ perms: perms,
58
70
  jti: 'S4EMiESTDe6k',
59
71
  };
60
- payload.perms = perms || {};
61
72
  const token = await this.jwtService.signAsync(payload);
62
73
  return { token };
63
74
  }
64
75
 
76
+ async getRoomToken({
77
+ roomId,
78
+ spaceId,
79
+ userId,
80
+ readonly = false,
81
+ }: {
82
+ roomId: string;
83
+ spaceId: string;
84
+ userId: string;
85
+ readonly: boolean;
86
+ }) {
87
+ let room = await this.getRoom(roomId);
88
+ if (!room) {
89
+ room = await this.createRoom({
90
+ _id: roomId,
91
+ name: 'Room ' + roomId,
92
+ });
93
+ }
94
+
95
+ let member = await this.getRoomMember(roomId, userId);
96
+ if (!member) {
97
+ member = await this.createRoomMember(room, {
98
+ userId,
99
+ });
100
+ }
101
+
102
+ const scopes = readonly ? READ_ACCESS : member.scopes;
103
+
104
+ const perms = {
105
+ [roomId]: scopes,
106
+ };
107
+
108
+ return await this.getToken({
109
+ spaceId,
110
+ userId,
111
+ perms,
112
+ });
113
+ }
114
+
65
115
  async getAttachmentById(attachmentId: string): Promise<Attachment> {
66
116
  // 模拟从数据库获取附件
67
117
  // 实际实现中应替换为数据库查询
@@ -147,6 +197,30 @@ export class RoomsService {
147
197
  return threads;
148
198
  }
149
199
 
200
+ async getThreadsByIds(
201
+ notifications: {
202
+ id: string;
203
+ userId: string;
204
+ kind: string;
205
+ notifiedAt?: Date;
206
+ readAt?: Date;
207
+ roomId: string;
208
+ threadId: string;
209
+ }[],
210
+ ) {
211
+ const threadPromises = [];
212
+ for (let i = 0; i < notifications.length; i++) {
213
+ const notification = notifications[i];
214
+ threadPromises.push(
215
+ this.getThread(notification.roomId, notification.threadId),
216
+ );
217
+ }
218
+ if (threadPromises.length > 0) {
219
+ return Promise.all(threadPromises);
220
+ }
221
+ return [];
222
+ }
223
+
150
224
  async getComments(roomId: string, threadId: string) {
151
225
  const comments = await this.mongodbService.find('b6_comments', {
152
226
  roomId: roomId,
@@ -245,6 +319,35 @@ export class RoomsService {
245
319
  result.attachments.push(attachment);
246
320
  }
247
321
 
322
+ // 如果有 @ mention 的时候,自动创建 b6_notifications 记录。
323
+ const { content } = body as CommentBody;
324
+ let notificationsPromises: Promise<any>[];
325
+ const mentionUsers: string[] = [];
326
+ for (const message of content) {
327
+ if (message.type === CommentType.Paragraph) {
328
+ message.children
329
+ .filter(
330
+ (child: CommentBodyMention) =>
331
+ child?.type === CommentBodyInlineType.Mention,
332
+ )
333
+ .forEach((child: CommentBodyMention) => mentionUsers.push(child.id));
334
+ }
335
+ }
336
+ if (mentionUsers && mentionUsers.length > 0) {
337
+ notificationsPromises = uniq(mentionUsers).map((userId) => {
338
+ return this.notificationsService.createThreadNotification({
339
+ _id: uuidv4(),
340
+ id: uuidv4(),
341
+ userId,
342
+ kind: 'thread',
343
+ notifiedAt: new Date(),
344
+ readAt: null,
345
+ roomId,
346
+ threadId,
347
+ });
348
+ });
349
+ await Promise.all(notificationsPromises);
350
+ }
248
351
  delete result['_id'];
249
352
  delete result['attachmentIds'];
250
353
  return result;
@@ -387,4 +490,105 @@ export class RoomsService {
387
490
 
388
491
  return null;
389
492
  }
493
+
494
+ async createRoom({
495
+ _id,
496
+ name,
497
+ description = '',
498
+ membershipType = 'standard',
499
+ members = [],
500
+ defaultNotifications = ['replies', 'mentions'],
501
+ defaultScopes = ['room:write'],
502
+ }: RoomDTO): Promise<RoomDTO> {
503
+ const newRoom = {
504
+ createdAt: new Date().toISOString(),
505
+ updatedAt: new Date().toISOString(),
506
+ _id,
507
+ name,
508
+ description,
509
+ membershipType,
510
+ defaultNotifications,
511
+ defaultScopes,
512
+ };
513
+
514
+ const room = await this.mongodbService.insertOne('b6_rooms', newRoom);
515
+
516
+ // 循环 members,执行 createRoomMember,并保存到 result.members
517
+ room.members = [];
518
+ for (const member of members) {
519
+ const newMember = await this.createRoomMember(room, member);
520
+ room.members.push(newMember);
521
+ }
522
+
523
+ return room;
524
+ }
525
+
526
+ async createRoomMember(room: RoomDTO, member: RoomMemberDTO) {
527
+ const {
528
+ _id,
529
+ userId,
530
+ roles = [],
531
+ notifications = room.defaultNotifications,
532
+ scopes = room.defaultScopes,
533
+ } = member;
534
+ const newMember = {
535
+ _id,
536
+ userId,
537
+ roles,
538
+ roomId: room._id,
539
+ notifications,
540
+ scopes,
541
+ createdAt: new Date().toISOString(),
542
+ };
543
+
544
+ const result = await this.mongodbService.insertOne(
545
+ 'b6_room_members',
546
+ newMember,
547
+ );
548
+ return result;
549
+ }
550
+
551
+ async getRoom(roomId: string) {
552
+ const room = await this.mongodbService.findOne('b6_rooms', {
553
+ _id: roomId,
554
+ });
555
+
556
+ if (!room) {
557
+ return null;
558
+ }
559
+
560
+ room.members = await this.getRoomMembers(roomId);
561
+ return room;
562
+ }
563
+
564
+ async getRoomMembers(roomId: string) {
565
+ const members = await this.mongodbService.find('b6_room_members', {
566
+ roomId,
567
+ });
568
+
569
+ return members;
570
+ }
571
+
572
+ async getRoomMember(roomId: string, userId: string) {
573
+ const member = await this.mongodbService.findOne('b6_room_members', {
574
+ roomId,
575
+ userId,
576
+ });
577
+
578
+ return member;
579
+ }
580
+
581
+ async getMyRooms(userId: string) {
582
+ const roomMembers = await this.mongodbService.find('b6_room_members', {
583
+ userId,
584
+ });
585
+
586
+ const rooms = [];
587
+ for (const roomMember of roomMembers) {
588
+ const room = await this.getRoom(roomMember.roomId);
589
+ rooms.push(room);
590
+ }
591
+
592
+ return rooms;
593
+ }
390
594
  }
package/.eslintrc.js DELETED
@@ -1,25 +0,0 @@
1
- module.exports = {
2
- parser: '@typescript-eslint/parser',
3
- parserOptions: {
4
- project: 'tsconfig.json',
5
- tsconfigRootDir: __dirname,
6
- sourceType: 'module',
7
- },
8
- plugins: ['@typescript-eslint/eslint-plugin'],
9
- extends: [
10
- 'plugin:@typescript-eslint/recommended',
11
- 'plugin:prettier/recommended',
12
- ],
13
- root: true,
14
- env: {
15
- node: true,
16
- jest: true,
17
- },
18
- ignorePatterns: ['.eslintrc.js'],
19
- rules: {
20
- '@typescript-eslint/interface-name-prefix': 'off',
21
- '@typescript-eslint/explicit-function-return-type': 'off',
22
- '@typescript-eslint/explicit-module-boundary-types': 'off',
23
- '@typescript-eslint/no-explicit-any': 'off',
24
- },
25
- };