From f15e868b5a1c1757a4e81babb58a4121fa98f77b Mon Sep 17 00:00:00 2001 From: Ibinola Date: Thu, 27 Aug 2026 12:33:05 +0100 Subject: [PATCH 1/6] feat: enforce pagination bounds on list endpoints Closes #1301 Closes #1300 Closes #1299 Closes #1298 --- src/courses/courses.controller.spec.ts | 13 ++++ src/courses/courses.service.ts | 3 +- src/messaging/message.controller.ts | 13 +++- src/messaging/messaging.module.ts | 2 + src/messaging/messaging.service.spec.ts | 73 +++++++++++++++++++ src/messaging/messaging.service.ts | 27 +++++-- .../notifications.service.spec.ts | 4 + src/notifications/notifications.service.ts | 3 +- 8 files changed, 124 insertions(+), 14 deletions(-) diff --git a/src/courses/courses.controller.spec.ts b/src/courses/courses.controller.spec.ts index a629f39e..d29ef4f4 100644 --- a/src/courses/courses.controller.spec.ts +++ b/src/courses/courses.controller.spec.ts @@ -9,6 +9,8 @@ import { CourseVersion } from './entities/course-version.entity'; import { BulkOperation } from './entities/bulk-operation.entity'; import { PaginationService } from '../common/services/pagination.service'; import { User, UserRole } from '../users/entities/user.entity'; +import { OutboxService } from '../common/events/outbox.service'; +import { DataSource } from 'typeorm'; describe('CoursesController Pagination (#826)', () => { let controller: CoursesController; @@ -109,6 +111,15 @@ describe('CoursesController Pagination (#826)', () => { }), }; + const mockOutboxService = { + enqueue: jest.fn(), + enqueueStandalone: jest.fn(), + }; + + const mockDataSource = { + transaction: jest.fn(), + }; + beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [CoursesController], @@ -119,6 +130,8 @@ describe('CoursesController Pagination (#826)', () => { { provide: getRepositoryToken(CourseReview), useValue: {} }, { provide: getRepositoryToken(CourseVersion), useValue: {} }, { provide: getRepositoryToken(BulkOperation), useValue: {} }, + { provide: OutboxService, useValue: mockOutboxService }, + { provide: DataSource, useValue: mockDataSource }, { provide: EventEmitter2, useValue: { emit: jest.fn() } }, ], }).compile(); diff --git a/src/courses/courses.service.ts b/src/courses/courses.service.ts index d288957f..64f951ed 100644 --- a/src/courses/courses.service.ts +++ b/src/courses/courses.service.ts @@ -30,6 +30,7 @@ import { PaginationQueryDto } from '../common/dto/pagination.dto'; import { OffsetPaginatedResponse } from '../common/interfaces/pagination.interface'; import { PaginationService } from '../common/services/pagination.service'; +import { clampLimit } from '../common/utils/pagination.utils'; import { OutboxService } from '../common/events/outbox.service'; import { AnalyticsService } from '../analytics/analytics.service'; import { EventType } from '../analytics/entities/event.entity'; @@ -145,7 +146,7 @@ export class CoursesService { requestingUser?: User, query?: PaginationQueryDto, ): Promise> { - const limit = query?.limit ?? 20; + const limit = clampLimit(query?.limit); const isPrivileged = checkUserRole(requestingUser, ...PRIVILEGED_ROLES); const qb = this.courseRepo.createQueryBuilder('course'); diff --git a/src/messaging/message.controller.ts b/src/messaging/message.controller.ts index a3da7bdd..b4127701 100644 --- a/src/messaging/message.controller.ts +++ b/src/messaging/message.controller.ts @@ -1,7 +1,8 @@ -import { Controller, Post, Body, Get, Param, Patch, UseGuards } from '@nestjs/common'; +import { Controller, Post, Body, Get, Param, Patch, UseGuards, Query, Req } from '@nestjs/common'; import { MessagingService } from './messaging.service'; import { CreateMessageDto } from './message.dto'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; +import { PaginationQueryDto } from '../common/dto/pagination.dto'; @UseGuards(JwtAuthGuard) @Controller('messages') @@ -17,10 +18,14 @@ export class MessagingController { @Get('conversation/:otherUserId') async getConversation( @Param('otherUserId') otherUserId: string, - @Param('userId') userId: string, + @Req() req: any, + @Query() query?: PaginationQueryDto, ) { - // Assuming userId is retrieved from auth token via a custom decorator; placeholder for now - const conversation = await this.messagingService.getConversation(userId, otherUserId); + const conversation = await this.messagingService.getConversation( + req.user.id, + otherUserId, + query, + ); return { success: true, conversation }; } diff --git a/src/messaging/messaging.module.ts b/src/messaging/messaging.module.ts index e355fb17..49a6d1a7 100644 --- a/src/messaging/messaging.module.ts +++ b/src/messaging/messaging.module.ts @@ -9,6 +9,7 @@ import { Message } from './message.entity'; import { ConnectionSessionService } from './websocket-resilience/connection-session.service'; import { WebSocketResilienceService } from './websocket-resilience/websocket-resilience.service'; import { TracingService } from './tracing/tracing.service'; +import { PaginationService } from '../common/services/pagination.service'; @Module({ imports: [ @@ -21,6 +22,7 @@ import { TracingService } from './tracing/tracing.service'; ConnectionSessionService, WebSocketResilienceService, TracingService, + PaginationService, ], controllers: [MessagingController], exports: [MessagingService], diff --git a/src/messaging/messaging.service.spec.ts b/src/messaging/messaging.service.spec.ts index ae34b052..405b2752 100644 --- a/src/messaging/messaging.service.spec.ts +++ b/src/messaging/messaging.service.spec.ts @@ -5,6 +5,7 @@ import { MessagingService } from './messaging.service'; import { TracingService } from './tracing/tracing.service'; import { QUEUE_NAMES } from '../common/constants/queue.constants'; import { Message } from './message.entity'; +import { PaginationService } from '../common/services/pagination.service'; const mockSpan = { end: jest.fn() }; @@ -22,6 +23,7 @@ const mockMessageRepo = { save: jest.fn((msg) => Promise.resolve(msg)), find: jest.fn().mockResolvedValue([]), update: jest.fn().mockResolvedValue(undefined), + createQueryBuilder: jest.fn(), }; const mockTracingService = { @@ -33,12 +35,68 @@ describe('MessagingService', () => { let service: MessagingService; beforeEach(async () => { + const dataset = [ + { + id: 'msg-1', + senderId: 'user-1', + recipientId: 'user-2', + content: 'one', + createdAt: new Date('2026-01-01T00:00:00Z'), + }, + { + id: 'msg-2', + senderId: 'user-2', + recipientId: 'user-1', + content: 'two', + createdAt: new Date('2026-01-02T00:00:00Z'), + }, + { + id: 'msg-3', + senderId: 'user-1', + recipientId: 'user-2', + content: 'three', + createdAt: new Date('2026-01-03T00:00:00Z'), + }, + ]; + + mockMessageRepo.createQueryBuilder.mockImplementation(() => { + let whereParams: any = null; + let skipVal = 0; + let takeVal = 20; + const qb: any = { + where: jest.fn().mockImplementation((_cond, params) => { + whereParams = params; + return qb; + }), + orderBy: jest.fn().mockReturnThis(), + addOrderBy: jest.fn().mockReturnThis(), + skip: jest.fn().mockImplementation((val) => { + skipVal = val; + return qb; + }), + take: jest.fn().mockImplementation((val) => { + takeVal = val; + return qb; + }), + getManyAndCount: jest.fn().mockImplementation(async () => { + const items = dataset.filter( + (item) => + (item.senderId === whereParams.userId && item.recipientId === whereParams.otherUserId) || + (item.senderId === whereParams.otherUserId && item.recipientId === whereParams.userId), + ); + return [items.slice(skipVal, skipVal + takeVal), items.length]; + }), + }; + return qb; + }); + const module: TestingModule = await Test.createTestingModule({ providers: [ MessagingService, { provide: getQueueToken(QUEUE_NAMES.MESSAGE_QUEUE), useValue: mockQueue }, { provide: TracingService, useValue: mockTracingService }, { provide: getRepositoryToken(Message), useValue: mockMessageRepo }, + PaginationService, ], }).compile(); @@ -95,4 +153,19 @@ describe('MessagingService', () => { expect(status).toEqual({ waiting: 2, active: 1, completed: 3, failed: 0 }); }); }); + + describe('getConversation', () => { + it('should paginate conversation results and clamp the page size', async () => { + const result = await service.getConversation( + 'user-1', + 'user-2', + { page: 1, limit: 999 } as any, + ); + + expect(result.limit).toBe(100); + expect(result.data).toHaveLength(3); + expect(result.total).toBe(3); + expect(result.page).toBe(1); + }); + }); }); diff --git a/src/messaging/messaging.service.ts b/src/messaging/messaging.service.ts index 6c7bc190..96b637be 100644 --- a/src/messaging/messaging.service.ts +++ b/src/messaging/messaging.service.ts @@ -8,6 +8,9 @@ import { Queue, Job } from 'bull'; import { QUEUE_NAMES } from '../common/constants/queue.constants'; import { TracingService } from './tracing/tracing.service'; import { enrichWithCorrelation } from '../queues/utils/correlation-job.util'; +import { PaginationService } from '../common/services/pagination.service'; +import { PaginationQueryDto } from '../common/dto/pagination.dto'; +import { clampLimit } from '../common/utils/pagination.utils'; /** * Provides messaging operations. @@ -21,6 +24,7 @@ export class MessagingService { private readonly tracingService: TracingService, @InjectRepository(Message) private readonly messageRepo: Repository, + private readonly paginationService: PaginationService, ) {} /** @@ -50,16 +54,23 @@ export class MessagingService { } } - async getConversation(userId: string, otherUserId: string): Promise { + async getConversation( + userId: string, + otherUserId: string, + query?: PaginationQueryDto, + ): Promise { const span = this.tracingService.startSpan('get-conversation'); try { - return await this.messageRepo.find({ - where: [ - { senderId: userId, recipientId: otherUserId }, - { senderId: otherUserId, recipientId: userId }, - ], - order: { createdAt: 'ASC' }, - }); + const limit = clampLimit(query?.limit); + const offset = query?.offset ?? (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); + const qb = this.messageRepo + .createQueryBuilder('message') + .where( + '(message.senderId = :userId AND message.recipientId = :otherUserId) OR (message.senderId = :otherUserId AND message.recipientId = :userId)', + { userId, otherUserId }, + ); + + return this.paginationService.paginate(qb, query?.cursor, limit, offset, 'createdAt'); } finally { this.tracingService.endSpan(span); } diff --git a/src/notifications/notifications.service.spec.ts b/src/notifications/notifications.service.spec.ts index 40229124..f8b5d25f 100644 --- a/src/notifications/notifications.service.spec.ts +++ b/src/notifications/notifications.service.spec.ts @@ -1,3 +1,7 @@ +jest.mock('./templates/notification-template.service', () => ({ + NotificationTemplateService: class NotificationTemplateService {}, +})); + import { NotificationsService } from './notifications.service'; import { NotificationType } from './entities/notification.entity'; diff --git a/src/notifications/notifications.service.ts b/src/notifications/notifications.service.ts index 74b9b1df..6aca1caa 100644 --- a/src/notifications/notifications.service.ts +++ b/src/notifications/notifications.service.ts @@ -9,6 +9,7 @@ import { CreateNotificationDto } from './dto/notification.dto'; import { SendTemplatedNotificationDto } from './dto/preferences.dto'; import { PreferencesService } from './preferences/preferences.service'; import { NotificationTemplateService } from './templates/notification-template.service'; +import { clampLimit } from '../common/utils/pagination.utils'; @Injectable() export class NotificationsService { @@ -193,7 +194,7 @@ export class NotificationsService { } async findForUser(userId: string, query?: PaginationQueryDto) { - const limit = query?.limit ?? 20; + const limit = clampLimit(query?.limit); const offset = query?.offset ?? (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); const qb = this.notificationRepository From 25d99b00f0da20f61fec6a70bb92afd7f1718b4c Mon Sep 17 00:00:00 2001 From: Ibinola Date: Thu, 27 Aug 2026 14:51:44 +0100 Subject: [PATCH 2/6] fix: format messaging pagination tests --- src/messaging/messaging.service.spec.ts | 9 +++++++-- src/messaging/messaging.service.ts | 12 ++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/messaging/messaging.service.spec.ts b/src/messaging/messaging.service.spec.ts index 405b2752..06c68e6a 100644 --- a/src/messaging/messaging.service.spec.ts +++ b/src/messaging/messaging.service.spec.ts @@ -129,7 +129,9 @@ describe('MessagingService', () => { it('should throw when save fails', async () => { mockMessageRepo.save.mockRejectedValue(new Error('DB error')); - await expect(service.createMessage({ text: 'fail' } as any)).rejects.toThrow('DB error'); + await expect( + service.createMessage({ text: 'fail' } as any), + ).rejects.toThrow('DB error'); expect(mockTracingService.endSpan).toHaveBeenCalledWith(mockSpan); }); }); @@ -159,7 +161,10 @@ describe('MessagingService', () => { const result = await service.getConversation( 'user-1', 'user-2', - { page: 1, limit: 999 } as any, + { + page: 1, + limit: 999, + } as any, ); expect(result.limit).toBe(100); diff --git a/src/messaging/messaging.service.ts b/src/messaging/messaging.service.ts index 96b637be..36a29ae7 100644 --- a/src/messaging/messaging.service.ts +++ b/src/messaging/messaging.service.ts @@ -62,7 +62,9 @@ export class MessagingService { const span = this.tracingService.startSpan('get-conversation'); try { const limit = clampLimit(query?.limit); - const offset = query?.offset ?? (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); + const offset = + query?.offset ?? + (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); const qb = this.messageRepo .createQueryBuilder('message') .where( @@ -70,7 +72,13 @@ export class MessagingService { { userId, otherUserId }, ); - return this.paginationService.paginate(qb, query?.cursor, limit, offset, 'createdAt'); + return this.paginationService.paginate( + qb, + query?.cursor, + limit, + offset, + 'createdAt', + ); } finally { this.tracingService.endSpan(span); } From d3688e569a2e3219e1e878d9311d0e4e740c77aa Mon Sep 17 00:00:00 2001 From: Ibinola Date: Thu, 27 Aug 2026 15:07:02 +0100 Subject: [PATCH 3/6] fix: conform messaging formatting to lint --- src/messaging/messaging.service.spec.ts | 26 ++++++++++--------------- src/messaging/messaging.service.ts | 12 ++---------- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/src/messaging/messaging.service.spec.ts b/src/messaging/messaging.service.spec.ts index 06c68e6a..be4cca1f 100644 --- a/src/messaging/messaging.service.spec.ts +++ b/src/messaging/messaging.service.spec.ts @@ -79,11 +79,14 @@ describe('MessagingService', () => { return qb; }), getManyAndCount: jest.fn().mockImplementation(async () => { - const items = dataset.filter( - (item) => - (item.senderId === whereParams.userId && item.recipientId === whereParams.otherUserId) || - (item.senderId === whereParams.otherUserId && item.recipientId === whereParams.userId), - ); + const items = dataset.filter((item) => { + return ( + (item.senderId === whereParams.userId && + item.recipientId === whereParams.otherUserId) || + (item.senderId === whereParams.otherUserId && + item.recipientId === whereParams.userId) + ); + }); return [items.slice(skipVal, skipVal + takeVal), items.length]; }), }; @@ -129,9 +132,7 @@ describe('MessagingService', () => { it('should throw when save fails', async () => { mockMessageRepo.save.mockRejectedValue(new Error('DB error')); - await expect( - service.createMessage({ text: 'fail' } as any), - ).rejects.toThrow('DB error'); + await expect(service.createMessage({ text: 'fail' } as any)).rejects.toThrow('DB error'); expect(mockTracingService.endSpan).toHaveBeenCalledWith(mockSpan); }); }); @@ -158,14 +159,7 @@ describe('MessagingService', () => { describe('getConversation', () => { it('should paginate conversation results and clamp the page size', async () => { - const result = await service.getConversation( - 'user-1', - 'user-2', - { - page: 1, - limit: 999, - } as any, - ); + const result = await service.getConversation('user-1', 'user-2', { page: 1, limit: 999 } as any); expect(result.limit).toBe(100); expect(result.data).toHaveLength(3); diff --git a/src/messaging/messaging.service.ts b/src/messaging/messaging.service.ts index 36a29ae7..96b637be 100644 --- a/src/messaging/messaging.service.ts +++ b/src/messaging/messaging.service.ts @@ -62,9 +62,7 @@ export class MessagingService { const span = this.tracingService.startSpan('get-conversation'); try { const limit = clampLimit(query?.limit); - const offset = - query?.offset ?? - (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); + const offset = query?.offset ?? (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); const qb = this.messageRepo .createQueryBuilder('message') .where( @@ -72,13 +70,7 @@ export class MessagingService { { userId, otherUserId }, ); - return this.paginationService.paginate( - qb, - query?.cursor, - limit, - offset, - 'createdAt', - ); + return this.paginationService.paginate(qb, query?.cursor, limit, offset, 'createdAt'); } finally { this.tracingService.endSpan(span); } From 93655738c4aa5c7ad2f96a65ad4e7f4b552ccca3 Mon Sep 17 00:00:00 2001 From: Ibinola Date: Thu, 27 Aug 2026 15:16:19 +0100 Subject: [PATCH 4/6] fix: restore messaging lint formatting --- src/messaging/messaging.service.spec.ts | 19 ++++++++++++------- src/messaging/messaging.service.ts | 4 +++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/messaging/messaging.service.spec.ts b/src/messaging/messaging.service.spec.ts index be4cca1f..907b4a96 100644 --- a/src/messaging/messaging.service.spec.ts +++ b/src/messaging/messaging.service.spec.ts @@ -79,14 +79,13 @@ describe('MessagingService', () => { return qb; }), getManyAndCount: jest.fn().mockImplementation(async () => { - const items = dataset.filter((item) => { - return ( + const items = dataset.filter( + (item) => (item.senderId === whereParams.userId && item.recipientId === whereParams.otherUserId) || (item.senderId === whereParams.otherUserId && - item.recipientId === whereParams.userId) - ); - }); + item.recipientId === whereParams.userId), + ); return [items.slice(skipVal, skipVal + takeVal), items.length]; }), }; @@ -132,7 +131,9 @@ describe('MessagingService', () => { it('should throw when save fails', async () => { mockMessageRepo.save.mockRejectedValue(new Error('DB error')); - await expect(service.createMessage({ text: 'fail' } as any)).rejects.toThrow('DB error'); + await expect( + service.createMessage({ text: 'fail' } as any), + ).rejects.toThrow('DB error'); expect(mockTracingService.endSpan).toHaveBeenCalledWith(mockSpan); }); }); @@ -159,7 +160,11 @@ describe('MessagingService', () => { describe('getConversation', () => { it('should paginate conversation results and clamp the page size', async () => { - const result = await service.getConversation('user-1', 'user-2', { page: 1, limit: 999 } as any); + const result = await service.getConversation( + 'user-1', + 'user-2', + { page: 1, limit: 999 } as any, + ); expect(result.limit).toBe(100); expect(result.data).toHaveLength(3); diff --git a/src/messaging/messaging.service.ts b/src/messaging/messaging.service.ts index 96b637be..3dbcc2e2 100644 --- a/src/messaging/messaging.service.ts +++ b/src/messaging/messaging.service.ts @@ -62,7 +62,9 @@ export class MessagingService { const span = this.tracingService.startSpan('get-conversation'); try { const limit = clampLimit(query?.limit); - const offset = query?.offset ?? (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); + const offset = + query?.offset ?? + (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); const qb = this.messageRepo .createQueryBuilder('message') .where( From 1aec65cc6caab858f3ddadb91f85d27d4ebb430c Mon Sep 17 00:00:00 2001 From: Ibinola Date: Thu, 27 Aug 2026 20:32:33 +0100 Subject: [PATCH 5/6] fix: align messaging formatting with lint --- src/messaging/messaging.service.spec.ts | 19 +++++++------------ src/messaging/messaging.service.ts | 4 +--- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/messaging/messaging.service.spec.ts b/src/messaging/messaging.service.spec.ts index 907b4a96..739f21ef 100644 --- a/src/messaging/messaging.service.spec.ts +++ b/src/messaging/messaging.service.spec.ts @@ -81,10 +81,8 @@ describe('MessagingService', () => { getManyAndCount: jest.fn().mockImplementation(async () => { const items = dataset.filter( (item) => - (item.senderId === whereParams.userId && - item.recipientId === whereParams.otherUserId) || - (item.senderId === whereParams.otherUserId && - item.recipientId === whereParams.userId), + (item.senderId === whereParams.userId && item.recipientId === whereParams.otherUserId) || + (item.senderId === whereParams.otherUserId && item.recipientId === whereParams.userId), ); return [items.slice(skipVal, skipVal + takeVal), items.length]; }), @@ -131,9 +129,7 @@ describe('MessagingService', () => { it('should throw when save fails', async () => { mockMessageRepo.save.mockRejectedValue(new Error('DB error')); - await expect( - service.createMessage({ text: 'fail' } as any), - ).rejects.toThrow('DB error'); + await expect(service.createMessage({ text: 'fail' } as any)).rejects.toThrow('DB error'); expect(mockTracingService.endSpan).toHaveBeenCalledWith(mockSpan); }); }); @@ -160,11 +156,10 @@ describe('MessagingService', () => { describe('getConversation', () => { it('should paginate conversation results and clamp the page size', async () => { - const result = await service.getConversation( - 'user-1', - 'user-2', - { page: 1, limit: 999 } as any, - ); + const result = await service.getConversation('user-1', 'user-2', { + page: 1, + limit: 999, + } as any); expect(result.limit).toBe(100); expect(result.data).toHaveLength(3); diff --git a/src/messaging/messaging.service.ts b/src/messaging/messaging.service.ts index 3dbcc2e2..96b637be 100644 --- a/src/messaging/messaging.service.ts +++ b/src/messaging/messaging.service.ts @@ -62,9 +62,7 @@ export class MessagingService { const span = this.tracingService.startSpan('get-conversation'); try { const limit = clampLimit(query?.limit); - const offset = - query?.offset ?? - (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); + const offset = query?.offset ?? (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); const qb = this.messageRepo .createQueryBuilder('message') .where( From 56e4a1c1e902dd700eeec39f94dc783be8a366a9 Mon Sep 17 00:00:00 2001 From: Ibinola Date: Thu, 27 Aug 2026 20:49:21 +0100 Subject: [PATCH 6/6] fix: match messaging formatting to lint --- src/messaging/messaging.service.spec.ts | 6 ++++-- src/messaging/messaging.service.ts | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/messaging/messaging.service.spec.ts b/src/messaging/messaging.service.spec.ts index 739f21ef..dc043fe9 100644 --- a/src/messaging/messaging.service.spec.ts +++ b/src/messaging/messaging.service.spec.ts @@ -81,8 +81,10 @@ describe('MessagingService', () => { getManyAndCount: jest.fn().mockImplementation(async () => { const items = dataset.filter( (item) => - (item.senderId === whereParams.userId && item.recipientId === whereParams.otherUserId) || - (item.senderId === whereParams.otherUserId && item.recipientId === whereParams.userId), + (item.senderId === whereParams.userId && + item.recipientId === whereParams.otherUserId) || + (item.senderId === whereParams.otherUserId && + item.recipientId === whereParams.userId), ); return [items.slice(skipVal, skipVal + takeVal), items.length]; }), diff --git a/src/messaging/messaging.service.ts b/src/messaging/messaging.service.ts index 96b637be..1f0d393f 100644 --- a/src/messaging/messaging.service.ts +++ b/src/messaging/messaging.service.ts @@ -62,7 +62,8 @@ export class MessagingService { const span = this.tracingService.startSpan('get-conversation'); try { const limit = clampLimit(query?.limit); - const offset = query?.offset ?? (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); + const offset = + query?.offset ?? (query?.cursor ? undefined : ((query?.page ?? 1) - 1) * limit); const qb = this.messageRepo .createQueryBuilder('message') .where(